Merge "Fix package name in StatusBarPopupChips flag file" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 2f843f9..8547ec1 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -1809,12 +1809,25 @@
     name: "aconfig_settingslib_flags",
     package: "com.android.settingslib.flags",
     container: "system",
+    exportable: true,
     srcs: [
         "packages/SettingsLib/aconfig/settingslib.aconfig",
     ],
 }
 
 java_aconfig_library {
+    name: "aconfig_settingslib_exported_flags_java_lib",
+    aconfig_declarations: "aconfig_settingslib_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+    mode: "exported",
+    min_sdk_version: "30",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.permission",
+    ],
+}
+
+java_aconfig_library {
     name: "aconfig_settingslib_flags_java_lib",
     aconfig_declarations: "aconfig_settingslib_flags",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
diff --git a/MEMORY_OWNERS b/MEMORY_OWNERS
index 89ce5140..12aa295 100644
--- a/MEMORY_OWNERS
+++ b/MEMORY_OWNERS
@@ -2,5 +2,4 @@
 tjmercier@google.com
 kaleshsingh@google.com
 jyescas@google.com
-carlosgalo@google.com
 jji@google.com
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index c775280..ed669be 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -63,12 +63,14 @@
 
     @Test
     @Parameters(method = "getData")
-    public void timeZipFileOpenClose(int numEntries) throws Exception {
+    public void timeZipFileOpen(int numEntries) throws Exception {
         setUp(numEntries);
         BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             ZipFile zf = new ZipFile(mFile);
+            state.pauseTiming();
             zf.close();
+            state.resumeTiming();
         }
     }
 
diff --git a/apex/jobscheduler/framework/aconfig/job.aconfig b/apex/jobscheduler/framework/aconfig/job.aconfig
index 63624d8..8b1a40c 100644
--- a/apex/jobscheduler/framework/aconfig/job.aconfig
+++ b/apex/jobscheduler/framework/aconfig/job.aconfig
@@ -55,3 +55,14 @@
     description: "Introduce a new getPendingJobReasonsHistory() API which returns a limited historical view of getPendingJobReasons()."
     bug: "372031023"
 }
+
+
+flag {
+    name: "add_type_info_to_wakelock_tag"
+    namespace: "backstage_power"
+    description: "Append the job type info to wakelock tag"
+    bug: "381880530"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
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 4335cae..fe6daa5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -5766,6 +5766,41 @@
     }
 
     // Shell command infrastructure
+    int getJobWakelockTag(PrintWriter pw, String pkgName, int userId, @Nullable String namespace,
+            int jobId) {
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+            if (uid < 0) {
+                pw.print("unknown(");
+                pw.print(pkgName);
+                pw.println(")");
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, namespace, jobId);
+                if (DEBUG) {
+                    Slog.d(TAG, "get-job-wakelock-tag " + namespace
+                            + "/" + uid + "/" + jobId + ": " + js);
+                }
+                if (js == null) {
+                    pw.print("unknown(");
+                    UserHandle.formatUid(pw, uid);
+                    pw.print("/jid");
+                    pw.print(jobId);
+                    pw.println(")");
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                pw.println(js.getWakelockTag());
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
     int getJobState(PrintWriter pw, String pkgName, int userId, @Nullable String namespace,
             int jobId) {
         try {
@@ -5945,6 +5980,9 @@
             pw.print(android.app.job.Flags.FLAG_GET_PENDING_JOB_REASONS_HISTORY_API,
                     android.app.job.Flags.getPendingJobReasonsHistoryApi());
             pw.println();
+            pw.print(android.app.job.Flags.FLAG_ADD_TYPE_INFO_TO_WAKELOCK_TAG,
+                    android.app.job.Flags.addTypeInfoToWakelockTag());
+            pw.println();
             pw.decreaseIndent();
             pw.println();
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 42c8250..633598e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -86,6 +86,8 @@
                     return getTransferredNetworkBytes(pw, BYTE_OPTION_DOWNLOAD);
                 case "get-transferred-upload-bytes":
                     return getTransferredNetworkBytes(pw, BYTE_OPTION_UPLOAD);
+                case "get-job-wakelock-tag":
+                    return getJobWakelockTag(pw);
                 case "get-job-state":
                     return getJobState(pw);
                 case "heartbeat":
@@ -424,6 +426,9 @@
             case android.app.job.Flags.FLAG_JOB_DEBUG_INFO_APIS:
                 pw.println(android.app.job.Flags.jobDebugInfoApis());
                 break;
+            case android.app.job.Flags.FLAG_ADD_TYPE_INFO_TO_WAKELOCK_TAG:
+                pw.println(android.app.job.Flags.addTypeInfoToWakelockTag());
+                break;
             case com.android.server.job.Flags.FLAG_BATCH_ACTIVE_BUCKET_JOBS:
                 pw.println(com.android.server.job.Flags.batchActiveBucketJobs());
                 break;
@@ -581,6 +586,49 @@
         }
     }
 
+    private int getJobWakelockTag(PrintWriter pw) throws Exception {
+        checkPermission("get job wakelock tag");
+
+        int userId = UserHandle.USER_SYSTEM;
+        String namespace = null;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                case "-n":
+                case "--namespace":
+                    namespace = getNextArgRequired();
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final String pkgName = getNextArgRequired();
+        final String jobIdStr = getNextArgRequired();
+        final int jobId = Integer.parseInt(jobIdStr);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            int ret = mInternal.getJobWakelockTag(pw, pkgName, userId, namespace, jobId);
+            printError(ret, pkgName, userId, namespace, jobId);
+            return ret;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     private int getJobState(PrintWriter pw) throws Exception {
         checkPermission("get job state");
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 5a33aa0..4b9d736 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -1459,7 +1459,12 @@
     @NonNull
     public String getWakelockTag() {
         if (mWakelockTag == null) {
-            mWakelockTag = "*job*/" + this.batteryName;
+            mWakelockTag = "*job*";
+            if (android.app.job.Flags.addTypeInfoToWakelockTag()) {
+                mWakelockTag += (isRequestedExpeditedJob()
+                    ? "e" : (getJob().isUserInitiated() ? "u" : "r"));
+            }
+            mWakelockTag += "/" + this.batteryName;
         }
         return mWakelockTag;
     }
diff --git a/api/api.go b/api/api.go
index e4d783e..cbdb7e8 100644
--- a/api/api.go
+++ b/api/api.go
@@ -105,7 +105,7 @@
 
 func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	ctx.WalkDeps(func(child, parent android.Module) bool {
-		if _, ok := child.(java.AndroidLibraryDependency); ok && child.Name() != "framework-res" {
+		if _, ok := android.OtherModuleProvider(ctx, child, java.AndroidLibraryInfoProvider); ok && child.Name() != "framework-res" {
 			// Stubs of BCP and SSCP libraries should not have any dependencies on apps
 			// This check ensures that we do not run into circular dependencies when UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT=true
 			ctx.ModuleErrorf(
diff --git a/boot/Android.bp b/boot/Android.bp
index eaa984a..f4ef1df 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -76,8 +76,8 @@
             module: "art-bootclasspath-fragment",
         },
         {
-            apex: "com.android.btservices",
-            module: "com.android.btservices-bootclasspath-fragment",
+            apex: "com.android.bt",
+            module: "com.android.bt-bootclasspath-fragment",
         },
         {
             apex: "com.android.configinfrastructure",
diff --git a/core/api/current.txt b/core/api/current.txt
index 32507df..d0b3a51 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9190,37 +9190,37 @@
 package android.app.jank {
 
   @FlaggedApi("android.app.jank.detailed_app_jank_metrics_api") public final class AppJankStats {
-    ctor public AppJankStats(int, @NonNull String, @Nullable String, @Nullable String, long, long, @NonNull android.app.jank.FrameOverrunHistogram);
-    method @NonNull public android.app.jank.FrameOverrunHistogram getFrameOverrunHistogram();
+    ctor public AppJankStats(int, @NonNull String, @Nullable String, @Nullable String, long, long, @NonNull android.app.jank.RelativeFrameTimeHistogram);
     method public long getJankyFrameCount();
+    method @NonNull public android.app.jank.RelativeFrameTimeHistogram getRelativeFrameTimeHistogram();
     method public long getTotalFrameCount();
     method public int getUid();
     method @NonNull public String getWidgetCategory();
     method @NonNull public String getWidgetId();
     method @NonNull public String getWidgetState();
-    field public static final String ANIMATING = "animating";
-    field public static final String ANIMATION = "animation";
-    field public static final String DRAGGING = "dragging";
-    field public static final String FLINGING = "flinging";
-    field public static final String KEYBOARD = "keyboard";
-    field public static final String MEDIA = "media";
-    field public static final String NAVIGATION = "navigation";
-    field public static final String NONE = "none";
-    field public static final String OTHER = "other";
-    field public static final String PLAYBACK = "playback";
-    field public static final String PREDICTIVE_BACK = "predictive_back";
-    field public static final String SCROLL = "scroll";
-    field public static final String SCROLLING = "scrolling";
-    field public static final String SWIPING = "swiping";
-    field public static final String TAPPING = "tapping";
-    field public static final String WIDGET_CATEGORY_UNSPECIFIED = "widget_category_unspecified";
-    field public static final String WIDGET_STATE_UNSPECIFIED = "widget_state_unspecified";
-    field public static final String ZOOMING = "zooming";
+    field public static final String WIDGET_CATEGORY_ANIMATION = "animation";
+    field public static final String WIDGET_CATEGORY_KEYBOARD = "keyboard";
+    field public static final String WIDGET_CATEGORY_MEDIA = "media";
+    field public static final String WIDGET_CATEGORY_NAVIGATION = "navigation";
+    field public static final String WIDGET_CATEGORY_OTHER = "other";
+    field public static final String WIDGET_CATEGORY_SCROLL = "scroll";
+    field public static final String WIDGET_CATEGORY_UNSPECIFIED = "unspecified";
+    field public static final String WIDGET_STATE_ANIMATING = "animating";
+    field public static final String WIDGET_STATE_DRAGGING = "dragging";
+    field public static final String WIDGET_STATE_FLINGING = "flinging";
+    field public static final String WIDGET_STATE_NONE = "none";
+    field public static final String WIDGET_STATE_PLAYBACK = "playback";
+    field public static final String WIDGET_STATE_PREDICTIVE_BACK = "predictive_back";
+    field public static final String WIDGET_STATE_SCROLLING = "scrolling";
+    field public static final String WIDGET_STATE_SWIPING = "swiping";
+    field public static final String WIDGET_STATE_TAPPING = "tapping";
+    field public static final String WIDGET_STATE_UNSPECIFIED = "unspecified";
+    field public static final String WIDGET_STATE_ZOOMING = "zooming";
   }
 
-  @FlaggedApi("android.app.jank.detailed_app_jank_metrics_api") public class FrameOverrunHistogram {
-    ctor public FrameOverrunHistogram();
-    method public void addFrameOverrunMillis(int);
+  @FlaggedApi("android.app.jank.detailed_app_jank_metrics_api") public class RelativeFrameTimeHistogram {
+    ctor public RelativeFrameTimeHistogram();
+    method public void addRelativeFrameTimeMillis(int);
     method @NonNull public int[] getBucketCounters();
     method @NonNull public int[] getBucketEndpointsMillis();
   }
@@ -20781,11 +20781,11 @@
     method @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public void registerDisplayListener(@NonNull java.util.concurrent.Executor, long, @NonNull android.hardware.display.DisplayManager.DisplayListener);
     method public void unregisterDisplayListener(android.hardware.display.DisplayManager.DisplayListener);
     field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
-    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_ADDED = 1L; // 0x1L
-    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_CHANGED = 4L; // 0x4L
-    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_REFRESH_RATE = 8L; // 0x8L
-    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_REMOVED = 2L; // 0x2L
-    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_FLAG_DISPLAY_STATE = 16L; // 0x10L
+    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_TYPE_DISPLAY_ADDED = 1L; // 0x1L
+    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_TYPE_DISPLAY_CHANGED = 4L; // 0x4L
+    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_TYPE_DISPLAY_REFRESH_RATE = 8L; // 0x8L
+    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_TYPE_DISPLAY_REMOVED = 2L; // 0x2L
+    field @FlaggedApi("com.android.server.display.feature.flags.display_listener_performance_improvements") public static final long EVENT_TYPE_DISPLAY_STATE = 16L; // 0x10L
     field public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; // 0x2
     field public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; // 0x0
     field public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; // 0x1
@@ -42521,7 +42521,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.GetValueRequest> CREATOR;
   }
 
-  public static final class GetValueRequest.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class GetValueRequest.Builder {
     ctor public GetValueRequest.Builder(@NonNull String, @NonNull String);
     method @NonNull public android.service.settings.preferences.GetValueRequest build();
   }
@@ -42542,7 +42542,7 @@
     field public static final int RESULT_UNSUPPORTED = 1; // 0x1
   }
 
-  public static final class GetValueResult.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class GetValueResult.Builder {
     ctor public GetValueResult.Builder(int);
     method @NonNull public android.service.settings.preferences.GetValueResult build();
     method @NonNull public android.service.settings.preferences.GetValueResult.Builder setMetadata(@Nullable android.service.settings.preferences.SettingsPreferenceMetadata);
@@ -42555,7 +42555,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.MetadataRequest> CREATOR;
   }
 
-  public static final class MetadataRequest.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class MetadataRequest.Builder {
     ctor public MetadataRequest.Builder();
     method @NonNull public android.service.settings.preferences.MetadataRequest build();
   }
@@ -42571,7 +42571,7 @@
     field public static final int RESULT_UNSUPPORTED = 1; // 0x1
   }
 
-  public static final class MetadataResult.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class MetadataResult.Builder {
     ctor public MetadataResult.Builder(int);
     method @NonNull public android.service.settings.preferences.MetadataResult build();
     method @NonNull public android.service.settings.preferences.MetadataResult.Builder setMetadataList(@NonNull java.util.List<android.service.settings.preferences.SettingsPreferenceMetadata>);
@@ -42586,7 +42586,7 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SetValueRequest> CREATOR;
   }
 
-  public static final class SetValueRequest.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class SetValueRequest.Builder {
     ctor public SetValueRequest.Builder(@NonNull String, @NonNull String, @NonNull android.service.settings.preferences.SettingsPreferenceValue);
     method @NonNull public android.service.settings.preferences.SetValueRequest build();
   }
@@ -42608,14 +42608,13 @@
     field public static final int RESULT_UNSUPPORTED = 1; // 0x1
   }
 
-  public static final class SetValueResult.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class SetValueResult.Builder {
     ctor public SetValueResult.Builder(int);
     method @NonNull public android.service.settings.preferences.SetValueResult build();
   }
 
   @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class SettingsPreferenceMetadata implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public java.util.List<java.lang.String> getBreadcrumbs();
     method @NonNull public android.os.Bundle getExtras();
     method @NonNull public String getKey();
     method @Nullable public android.content.Intent getLaunchIntent();
@@ -42631,17 +42630,16 @@
     method public boolean isWritable();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SettingsPreferenceMetadata> CREATOR;
+    field public static final int DEEPLINK_ONLY = 2; // 0x2
     field public static final int EXPECT_POST_CONFIRMATION = 1; // 0x1
-    field public static final int EXPECT_PRE_CONFIRMATION = 2; // 0x2
     field public static final int NO_DIRECT_ACCESS = 3; // 0x3
     field public static final int NO_SENSITIVITY = 0; // 0x0
   }
 
-  public static final class SettingsPreferenceMetadata.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class SettingsPreferenceMetadata.Builder {
     ctor public SettingsPreferenceMetadata.Builder(@NonNull String, @NonNull String);
     method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata build();
     method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setAvailable(boolean);
-    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setBreadcrumbs(@NonNull java.util.List<java.lang.String>);
     method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setEnabled(boolean);
     method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setExtras(@NonNull android.os.Bundle);
     method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setLaunchIntent(@Nullable android.content.Intent);
@@ -42688,7 +42686,7 @@
     field public static final int TYPE_STRING = 3; // 0x3
   }
 
-  public static final class SettingsPreferenceValue.Builder {
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final class SettingsPreferenceValue.Builder {
     ctor public SettingsPreferenceValue.Builder(int);
     method @NonNull public android.service.settings.preferences.SettingsPreferenceValue build();
     method @NonNull public android.service.settings.preferences.SettingsPreferenceValue.Builder setBooleanValue(boolean);
@@ -53484,9 +53482,9 @@
     field public static final int CHANGE_FRAME_RATE_ALWAYS = 1; // 0x1
     field public static final int CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS = 0; // 0x0
     field @NonNull public static final android.os.Parcelable.Creator<android.view.Surface> CREATOR;
+    field @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_gte_enum") public static final int FRAME_RATE_COMPATIBILITY_AT_LEAST = 2; // 0x2
     field public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; // 0x0
     field public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; // 0x1
-    field @FlaggedApi("com.android.graphics.surfaceflinger.flags.arr_setframerate_gte_enum") public static final int FRAME_RATE_COMPATIBILITY_GTE = 2; // 0x2
     field public static final int ROTATION_0 = 0; // 0x0
     field public static final int ROTATION_180 = 2; // 0x2
     field public static final int ROTATION_270 = 3; // 0x3
@@ -57120,6 +57118,7 @@
     method public void close();
     method @NonNull public final android.view.contentcapture.ContentCaptureSession createContentCaptureSession(@NonNull android.view.contentcapture.ContentCaptureContext);
     method public final void destroy();
+    method @FlaggedApi("android.view.contentcapture.flags.ccapi_baklava_enabled") public void flush();
     method @Nullable public final android.view.contentcapture.ContentCaptureContext getContentCaptureContext();
     method @NonNull public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId();
     method @NonNull public android.view.autofill.AutofillId newAutofillId(@NonNull android.view.autofill.AutofillId, long);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6d24e46..a60fd11 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -360,6 +360,7 @@
     field @Deprecated public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
     field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
+    field @FlaggedApi("android.content.pm.uid_based_provider_lookup") public static final String RESOLVE_COMPONENT_FOR_UID = "android.permission.RESOLVE_COMPONENT_FOR_UID";
     field public static final String RESTART_WIFI_SUBSYSTEM = "android.permission.RESTART_WIFI_SUBSYSTEM";
     field @FlaggedApi("android.permission.flags.health_connect_backup_restore_permission_enabled") public static final String RESTORE_HEALTH_CONNECT_DATA_AND_SETTINGS = "android.permission.RESTORE_HEALTH_CONNECT_DATA_AND_SETTINGS";
     field public static final String RESTORE_RUNTIME_PERMISSIONS = "android.permission.RESTORE_RUNTIME_PERMISSIONS";
@@ -4241,6 +4242,7 @@
     method public abstract void registerDexModule(@NonNull String, @Nullable android.content.pm.PackageManager.DexModuleRegisterCallback);
     method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public void replacePreferredActivity(@NonNull android.content.IntentFilter, int, @NonNull java.util.List<android.content.ComponentName>, @NonNull android.content.ComponentName);
+    method @FlaggedApi("android.content.pm.uid_based_provider_lookup") @Nullable @RequiresPermission(android.Manifest.permission.RESOLVE_COMPONENT_FOR_UID) public android.content.pm.ProviderInfo resolveContentProviderForUid(@NonNull String, @NonNull android.content.pm.PackageManager.ComponentInfoFlags, int);
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle, @NonNull String);
     method public void sendDeviceCustomizationReadyBroadcast();
@@ -5079,8 +5081,8 @@
   }
 
   @FlaggedApi("android.chre.flags.offload_api") public class HubEndpoint {
-    method @Nullable public android.hardware.contexthub.IHubEndpointLifecycleCallback getLifecycleCallback();
-    method @Nullable public android.hardware.contexthub.IHubEndpointMessageCallback getMessageCallback();
+    method @Nullable public android.hardware.contexthub.HubEndpointLifecycleCallback getLifecycleCallback();
+    method @Nullable public android.hardware.contexthub.HubEndpointMessageCallback getMessageCallback();
     method @NonNull public java.util.Collection<android.hardware.contexthub.HubServiceInfo> getServiceInfoCollection();
     method @Nullable public String getTag();
     method public int getVersion();
@@ -5095,14 +5097,19 @@
   public static final class HubEndpoint.Builder {
     ctor public HubEndpoint.Builder(@NonNull android.content.Context);
     method @NonNull public android.hardware.contexthub.HubEndpoint build();
-    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setLifecycleCallback(@NonNull android.hardware.contexthub.IHubEndpointLifecycleCallback);
-    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setLifecycleCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.IHubEndpointLifecycleCallback);
-    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setMessageCallback(@NonNull android.hardware.contexthub.IHubEndpointMessageCallback);
-    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.IHubEndpointMessageCallback);
+    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setLifecycleCallback(@NonNull android.hardware.contexthub.HubEndpointLifecycleCallback);
+    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setLifecycleCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.HubEndpointLifecycleCallback);
+    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setMessageCallback(@NonNull android.hardware.contexthub.HubEndpointMessageCallback);
+    method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.HubEndpointMessageCallback);
     method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setServiceInfoCollection(@NonNull java.util.Collection<android.hardware.contexthub.HubServiceInfo>);
     method @NonNull public android.hardware.contexthub.HubEndpoint.Builder setTag(@NonNull String);
   }
 
+  @FlaggedApi("android.chre.flags.offload_api") public interface HubEndpointDiscoveryCallback {
+    method public void onEndpointsStarted(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>);
+    method public void onEndpointsStopped(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>, int);
+  }
+
   @FlaggedApi("android.chre.flags.offload_api") public final class HubEndpointInfo implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.hardware.contexthub.HubEndpointInfo.HubEndpointIdentifier getIdentifier();
@@ -5126,6 +5133,16 @@
     method public long getHub();
   }
 
+  @FlaggedApi("android.chre.flags.offload_api") public interface HubEndpointLifecycleCallback {
+    method public void onSessionClosed(@NonNull android.hardware.contexthub.HubEndpointSession, int);
+    method @NonNull public android.hardware.contexthub.HubEndpointSessionResult onSessionOpenRequest(@NonNull android.hardware.contexthub.HubEndpointInfo, @Nullable String);
+    method public void onSessionOpened(@NonNull android.hardware.contexthub.HubEndpointSession);
+  }
+
+  @FlaggedApi("android.chre.flags.offload_api") public interface HubEndpointMessageCallback {
+    method public void onMessageReceived(@NonNull android.hardware.contexthub.HubEndpointSession, @NonNull android.hardware.contexthub.HubMessage);
+  }
+
   @FlaggedApi("android.chre.flags.offload_api") public class HubEndpointSession implements java.lang.AutoCloseable {
     method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void close();
     method @Nullable public String getServiceDescriptor();
@@ -5140,19 +5157,18 @@
   }
 
   @FlaggedApi("android.chre.flags.offload_api") public final class HubMessage implements android.os.Parcelable {
-    method @NonNull public static android.hardware.contexthub.HubMessage createMessage(int, @NonNull byte[]);
-    method @NonNull public static android.hardware.contexthub.HubMessage createMessage(int, @NonNull byte[], @NonNull android.hardware.contexthub.HubMessage.DeliveryParams);
     method public int describeContents();
     method @NonNull public byte[] getMessageBody();
     method public int getMessageType();
+    method public boolean isResponseRequired();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.contexthub.HubMessage> CREATOR;
   }
 
-  public static class HubMessage.DeliveryParams {
-    method public boolean isResponseRequired();
-    method @NonNull public static android.hardware.contexthub.HubMessage.DeliveryParams makeBasic();
-    method @NonNull public android.hardware.contexthub.HubMessage.DeliveryParams setResponseRequired(boolean);
+  public static final class HubMessage.Builder {
+    ctor public HubMessage.Builder(int, @NonNull byte[]);
+    method @NonNull public android.hardware.contexthub.HubMessage build();
+    method @NonNull public android.hardware.contexthub.HubMessage.Builder setResponseRequired(boolean);
   }
 
   @FlaggedApi("android.chre.flags.offload_api") public final class HubServiceInfo implements android.os.Parcelable {
@@ -5174,21 +5190,6 @@
     method @NonNull public android.hardware.contexthub.HubServiceInfo build();
   }
 
-  @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointDiscoveryCallback {
-    method public void onEndpointsStarted(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>);
-    method public void onEndpointsStopped(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>, int);
-  }
-
-  @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointLifecycleCallback {
-    method public void onSessionClosed(@NonNull android.hardware.contexthub.HubEndpointSession, int);
-    method @NonNull public android.hardware.contexthub.HubEndpointSessionResult onSessionOpenRequest(@NonNull android.hardware.contexthub.HubEndpointInfo, @Nullable String);
-    method public void onSessionOpened(@NonNull android.hardware.contexthub.HubEndpointSession);
-  }
-
-  @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointMessageCallback {
-    method public void onMessageReceived(@NonNull android.hardware.contexthub.HubEndpointSession, @NonNull android.hardware.contexthub.HubMessage);
-  }
-
 }
 
 package android.hardware.devicestate {
@@ -6192,16 +6193,16 @@
     method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
     method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler);
     method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpoint(@NonNull android.hardware.contexthub.HubEndpoint);
-    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
-    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor);
-    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
-    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor);
+    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.HubEndpointDiscoveryCallback, long);
+    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.HubEndpointDiscoveryCallback, long);
+    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.HubEndpointDiscoveryCallback, @NonNull String);
+    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.contexthub.HubEndpointDiscoveryCallback, @NonNull String);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int unloadNanoApp(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
     method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
     method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpoint(@NonNull android.hardware.contexthub.HubEndpoint);
-    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
+    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.HubEndpointDiscoveryCallback);
     field public static final int AUTHORIZATION_DENIED = 0; // 0x0
     field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1
     field public static final int AUTHORIZATION_GRANTED = 2; // 0x2
@@ -12259,7 +12260,6 @@
   }
 
   @FlaggedApi("com.android.server.telecom.flags.telecom_mainline_blocked_numbers_manager") public static final class BlockedNumbersManager.BlockSuppressionStatus {
-    ctor public BlockedNumbersManager.BlockSuppressionStatus(boolean, long);
     method public boolean getIsSuppressed();
     method public long getUntilTimestampMillis();
   }
@@ -12676,27 +12676,21 @@
 package android.security.advancedprotection {
 
   @FlaggedApi("android.security.aapm_api") public final class AdvancedProtectionFeature implements android.os.Parcelable {
-    ctor public AdvancedProtectionFeature(@NonNull String);
+    ctor public AdvancedProtectionFeature(int);
     method public int describeContents();
-    method @NonNull public String getId();
+    method public int getId();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.security.advancedprotection.AdvancedProtectionFeature> CREATOR;
   }
 
   @FlaggedApi("android.security.aapm_api") public final class AdvancedProtectionManager {
-    method @NonNull public android.content.Intent createSupportIntent(@NonNull String, @Nullable String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE) public java.util.List<android.security.advancedprotection.AdvancedProtectionFeature> getAdvancedProtectionFeatures();
     method @RequiresPermission(android.Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE) public void setAdvancedProtectionEnabled(boolean);
-    field @FlaggedApi("android.security.aapm_api") public static final String ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG = "android.security.advancedprotection.action.SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG";
-    field public static final String EXTRA_SUPPORT_DIALOG_FEATURE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_FEATURE";
-    field public static final String EXTRA_SUPPORT_DIALOG_TYPE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_TYPE";
-    field public static final String FEATURE_ID_DISALLOW_CELLULAR_2G = "android.security.advancedprotection.feature_disallow_2g";
-    field public static final String FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = "android.security.advancedprotection.feature_disallow_install_unknown_sources";
-    field public static final String FEATURE_ID_DISALLOW_USB = "android.security.advancedprotection.feature_disallow_usb";
-    field public static final String FEATURE_ID_DISALLOW_WEP = "android.security.advancedprotection.feature_disallow_wep";
-    field public static final String FEATURE_ID_ENABLE_MTE = "android.security.advancedprotection.feature_enable_mte";
-    field public static final String SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION = "android.security.advancedprotection.type_blocked_interaction";
-    field public static final String SUPPORT_DIALOG_TYPE_DISABLED_SETTING = "android.security.advancedprotection.type_disabled_setting";
+    field public static final int FEATURE_ID_DISALLOW_CELLULAR_2G = 0; // 0x0
+    field public static final int FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = 1; // 0x1
+    field public static final int FEATURE_ID_DISALLOW_USB = 2; // 0x2
+    field public static final int FEATURE_ID_DISALLOW_WEP = 3; // 0x3
+    field public static final int FEATURE_ID_ENABLE_MTE = 4; // 0x4
   }
 
 }
@@ -12734,9 +12728,9 @@
 package android.security.intrusiondetection {
 
   @FlaggedApi("android.security.afl_api") public final class IntrusionDetectionEvent implements android.os.Parcelable {
-    ctor public IntrusionDetectionEvent(@NonNull android.app.admin.SecurityLog.SecurityEvent);
-    ctor public IntrusionDetectionEvent(@NonNull android.app.admin.DnsEvent);
-    ctor public IntrusionDetectionEvent(@NonNull android.app.admin.ConnectEvent);
+    method @NonNull public static android.security.intrusiondetection.IntrusionDetectionEvent createForConnectEvent(@NonNull android.app.admin.ConnectEvent);
+    method @NonNull public static android.security.intrusiondetection.IntrusionDetectionEvent createForDnsEvent(@NonNull android.app.admin.DnsEvent);
+    method @NonNull public static android.security.intrusiondetection.IntrusionDetectionEvent createForSecurityEvent(@NonNull android.app.admin.SecurityLog.SecurityEvent);
     method @FlaggedApi("android.security.afl_api") public int describeContents();
     method @NonNull public android.app.admin.ConnectEvent getConnectEvent();
     method @NonNull public android.app.admin.DnsEvent getDnsEvent();
@@ -18688,7 +18682,7 @@
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForProvisionStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteProvisionStateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void registerForSatelliteDisallowedReasonsChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDisallowedReasonsCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSelectedNbIotSatelliteSubscriptionChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback);
-    method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSupportedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteSupportedStateCallback);
+    method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSupportedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void removeAttachRestrictionForCarrier(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestAttachEnabledForCarrier(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.satellite.SatelliteCapabilities,android.telephony.satellite.SatelliteManager.SatelliteException>);
@@ -18717,7 +18711,7 @@
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForProvisionStateChanged(@NonNull android.telephony.satellite.SatelliteProvisionStateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteDisallowedReasonsChanged(@NonNull android.telephony.satellite.SatelliteDisallowedReasonsCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSelectedNbIotSatelliteSubscriptionChanged(@NonNull android.telephony.satellite.SelectedNbIotSatelliteSubscriptionCallback);
-    method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSupportedStateChanged(@NonNull android.telephony.satellite.SatelliteSupportedStateCallback);
+    method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSupportedStateChanged(@NonNull java.util.function.Consumer<java.lang.Boolean>);
     field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String ACTION_SATELLITE_START_NON_EMERGENCY_SESSION = "android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION";
     field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED = "android.telephony.satellite.action.SATELLITE_SUBSCRIBER_ID_LIST_CHANGED";
     field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS = 7; // 0x7
@@ -18738,12 +18732,12 @@
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int DISPLAY_MODE_UNKNOWN = 0; // 0x0
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911 = 2; // 0x2
-    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = "android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 3; // 0x3
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 2; // 0x2
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 4; // 0x4
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = 0; // 0x0
+    field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final String PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT = "android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT = 2; // 0x2
     field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION = 1; // 0x1
     field @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static final int SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER = 0; // 0x0
@@ -18807,11 +18801,12 @@
   }
 
   @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteModemEnableRequestAttributes implements android.os.Parcelable {
+    ctor public SatelliteModemEnableRequestAttributes(boolean, boolean, boolean, @NonNull android.telephony.satellite.SatelliteSubscriptionInfo);
     method public int describeContents();
     method @NonNull public android.telephony.satellite.SatelliteSubscriptionInfo getSatelliteSubscriptionInfo();
-    method public boolean isDemoMode();
-    method public boolean isEmergencyMode();
     method public boolean isEnabled();
+    method public boolean isForDemoMode();
+    method public boolean isForEmergencyMode();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteModemEnableRequestAttributes> CREATOR;
   }
@@ -18821,9 +18816,10 @@
   }
 
   @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatellitePosition implements android.os.Parcelable {
+    ctor public SatellitePosition(@FloatRange(from=0xffffff4c, to=180) double, @FloatRange(from=0.0) double);
     method public int describeContents();
-    method public double getAltitudeKm();
-    method public double getLongitudeDegrees();
+    method @FloatRange(from=0.0) public double getAltitudeKm();
+    method @FloatRange(from=0xffffff4c, to=180) public double getLongitudeDegrees();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatellitePosition> CREATOR;
   }
@@ -18842,8 +18838,8 @@
     method public int getSubscriberIdType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteSubscriberInfo> CREATOR;
-    field public static final int ICCID = 0; // 0x0
-    field public static final int IMSI_MSISDN = 1; // 0x1
+    field public static final int SUBSCRIBER_ID_TYPE_ICCID = 0; // 0x0
+    field public static final int SUBSCRIBER_ID_TYPE_IMSI_MSISDN = 1; // 0x1
   }
 
   public static final class SatelliteSubscriberInfo.Builder {
@@ -18879,10 +18875,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteSubscriptionInfo> CREATOR;
   }
 
-  @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public interface SatelliteSupportedStateCallback {
-    method public void onSatelliteSupportedStateChanged(boolean);
-  }
-
   @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteTransmissionUpdateCallback {
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onReceiveDatagramStateChanged(int, int, int);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatellitePositionChanged(@NonNull android.telephony.satellite.PointingInfo);
@@ -18906,6 +18898,16 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SystemSelectionSpecifier> CREATOR;
   }
 
+  public static final class SystemSelectionSpecifier.Builder {
+    ctor public SystemSelectionSpecifier.Builder();
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier build();
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier.Builder setBands(@NonNull int[]);
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier.Builder setEarfcns(@NonNull int[]);
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier.Builder setMccMnc(@NonNull String);
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier.Builder setSatelliteInfos(@NonNull java.util.List<android.telephony.satellite.SatelliteInfo>);
+    method @NonNull public android.telephony.satellite.SystemSelectionSpecifier.Builder setTagIds(@NonNull int[]);
+  }
+
 }
 
 package android.text {
@@ -19091,6 +19093,7 @@
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureEvent> CREATOR;
     field public static final int TYPE_CONTEXT_UPDATED = 6; // 0x6
+    field @FlaggedApi("android.view.contentcapture.flags.ccapi_baklava_enabled") public static final int TYPE_SESSION_FLUSH = 11; // 0xb
     field public static final int TYPE_SESSION_PAUSED = 8; // 0x8
     field public static final int TYPE_SESSION_RESUMED = 7; // 0x7
     field public static final int TYPE_VIEW_APPEARED = 1; // 0x1
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 5171e68..f98fb46 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1677,6 +1677,7 @@
 
   @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_property_api") public final class DeviceState {
     ctor public DeviceState(@NonNull android.hardware.devicestate.DeviceState.Configuration);
+    field @FlaggedApi("android.hardware.devicestate.feature.flags.device_state_rdm_v2") public static final int PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT = 1001; // 0x3e9
     field public static final int PROPERTY_POLICY_AVAILABLE_FOR_APP_REQUEST = 8; // 0x8
   }
 
diff --git a/core/java/Android.bp b/core/java/Android.bp
index ce767f4..1e97d4f 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -223,6 +223,7 @@
         "android/os/IThermalService.aidl",
         "android/os/IPowerManager.aidl",
         "android/os/IWakeLockCallback.aidl",
+        "android/os/IScreenTimeoutPolicyListener.aidl",
     ],
 }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fee8cdb..c3ef104 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5834,7 +5834,11 @@
         final int size = permissions.length;
         int[] results = new int[size];
         for (int i = 0; i < size; i++) {
-            results[i] = deviceContext.getPermissionRequestState(permissions[i]);
+            if (permissions[i] == null) {
+                results[i] = Context.PERMISSION_REQUEST_STATE_UNREQUESTABLE;
+            } else {
+                results[i] = deviceContext.getPermissionRequestState(permissions[i]);
+            }
         }
         return results;
     }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index abdfb535..999db18 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -485,6 +485,11 @@
      */
     public static final int OOM_ADJ_REASON_FOLLOW_UP = 23;
 
+    /**
+     * Oom Adj Reason: Update after oom adjuster configuration has changed.
+     */
+    public static final int OOM_ADJ_REASON_RECONFIGURATION = 24;
+
     @IntDef(prefix = {"OOM_ADJ_REASON_"}, value = {
         OOM_ADJ_REASON_NONE,
         OOM_ADJ_REASON_ACTIVITY,
@@ -510,6 +515,7 @@
         OOM_ADJ_REASON_RESTRICTION_CHANGE,
         OOM_ADJ_REASON_COMPONENT_DISABLED,
         OOM_ADJ_REASON_FOLLOW_UP,
+        OOM_ADJ_REASON_RECONFIGURATION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface OomAdjReason {}
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 832c88a..af6978a 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1892,7 +1892,7 @@
      * app to pass through touch events to it when touches fall outside the content window.
      *
      * <p> By default, touches that fall on a translucent non-touchable area of an overlaying
-     * activity window are blocked from passing through to the activity below (source activity),
+     * activity window may be blocked from passing through to the activity below (source activity),
      * unless the overlaying activity is from the same UID as the source activity. The source
      * activity may use this method to opt in and allow the overlaying activities from the
      * to-be-launched app to pass through touches to itself. The source activity needs to ensure
@@ -1900,6 +1900,9 @@
      * attacks. The flag is ignored if the context calling
      * {@link Context#startActivity(Intent, Bundle)} is not an activity.
      *
+     * <p> Apps with target SDK 36 and above that depend on cross-uid pass-through touches must
+     * opt in to ensure that pass-through touches work correctly.
+     *
      * <p> For backward compatibility, apps with target SDK 35 and below may still receive
      * pass-through touches without opt-in if the cross-uid activity is launched by the source
      * activity.
diff --git a/core/java/android/app/AppCompatTaskInfo.java b/core/java/android/app/AppCompatTaskInfo.java
index 61b5687..599f1a8 100644
--- a/core/java/android/app/AppCompatTaskInfo.java
+++ b/core/java/android/app/AppCompatTaskInfo.java
@@ -27,6 +27,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 
 /**
  * Stores App Compat information about a particular Task.
@@ -58,16 +59,11 @@
     public int topActivityLetterboxHeight = PROPERTY_VALUE_UNSET;
 
     /**
-     * Contains the current app height of the letterboxed activity if available or
-     * {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
+     * Contains the app bounds of the top activity or size compat mode
+     * bounds when in size compat mode. If null, contains bounds.
      */
-    public int topActivityLetterboxAppHeight = PROPERTY_VALUE_UNSET;
-
-    /**
-     * Contains the current app  width of the letterboxed activity if available or
-     * {@link TaskInfo#PROPERTY_VALUE_UNSET} otherwise.
-     */
-    public int topActivityLetterboxAppWidth = PROPERTY_VALUE_UNSET;
+    @NonNull
+    public final Rect topActivityAppBounds = new Rect();
 
     /**
      * Contains the top activity bounds when the activity is letterboxed.
@@ -350,8 +346,7 @@
                 && topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
-                && topActivityLetterboxAppWidth == that.topActivityLetterboxAppWidth
-                && topActivityLetterboxAppHeight == that.topActivityLetterboxAppHeight
+                && topActivityAppBounds.equals(that.topActivityAppBounds)
                 && topActivityLetterboxHorizontalPosition
                     == that.topActivityLetterboxHorizontalPosition
                 && cameraCompatTaskInfo.equalsForTaskOrganizer(that.cameraCompatTaskInfo);
@@ -371,8 +366,7 @@
                     == that.topActivityLetterboxHorizontalPosition
                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
-                && topActivityLetterboxAppWidth == that.topActivityLetterboxAppWidth
-                && topActivityLetterboxAppHeight == that.topActivityLetterboxAppHeight
+                && topActivityAppBounds.equals(that.topActivityAppBounds)
                 && cameraCompatTaskInfo.equalsForCompatUi(that.cameraCompatTaskInfo);
     }
 
@@ -385,8 +379,7 @@
         topActivityLetterboxHorizontalPosition = source.readInt();
         topActivityLetterboxWidth = source.readInt();
         topActivityLetterboxHeight = source.readInt();
-        topActivityLetterboxAppWidth = source.readInt();
-        topActivityLetterboxAppHeight = source.readInt();
+        topActivityAppBounds.set(Objects.requireNonNull(source.readTypedObject(Rect.CREATOR)));
         topActivityLetterboxBounds = source.readTypedObject(Rect.CREATOR);
         cameraCompatTaskInfo = source.readTypedObject(CameraCompatTaskInfo.CREATOR);
     }
@@ -401,8 +394,7 @@
         dest.writeInt(topActivityLetterboxHorizontalPosition);
         dest.writeInt(topActivityLetterboxWidth);
         dest.writeInt(topActivityLetterboxHeight);
-        dest.writeInt(topActivityLetterboxAppWidth);
-        dest.writeInt(topActivityLetterboxAppHeight);
+        dest.writeTypedObject(topActivityAppBounds, flags);
         dest.writeTypedObject(topActivityLetterboxBounds, flags);
         dest.writeTypedObject(cameraCompatTaskInfo, flags);
     }
@@ -421,8 +413,7 @@
                 + topActivityLetterboxHorizontalPosition
                 + " topActivityLetterboxWidth=" + topActivityLetterboxWidth
                 + " topActivityLetterboxHeight=" + topActivityLetterboxHeight
-                + " topActivityLetterboxAppWidth=" + topActivityLetterboxAppWidth
-                + " topActivityLetterboxAppHeight=" + topActivityLetterboxAppHeight
+                + " topActivityAppBounds=" + topActivityAppBounds
                 + " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled()
                 + " isSystemFullscreenOverrideEnabled=" + isSystemFullscreenOverrideEnabled()
                 + " hasMinAspectRatioOverride=" + hasMinAspectRatioOverride()
diff --git a/core/java/android/app/AppOpsManager.aidl b/core/java/android/app/AppOpsManager.aidl
index b4dee2e..56ed290 100644
--- a/core/java/android/app/AppOpsManager.aidl
+++ b/core/java/android/app/AppOpsManager.aidl
@@ -19,6 +19,7 @@
 parcelable AppOpsManager.PackageOps;
 parcelable AppOpsManager.NoteOpEventProxyInfo;
 parcelable AppOpsManager.NoteOpEvent;
+parcelable AppOpsManager.NotedOp;
 parcelable AppOpsManager.OpFeatureEntry;
 parcelable AppOpsManager.OpEntry;
 
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1913812..efcd278 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -262,6 +262,23 @@
 
     private static final Object sLock = new Object();
 
+    // A map that records noted times for each op.
+    private static ArrayMap<NotedOp, Integer> sPendingNotedOps = new ArrayMap<>();
+    private static HandlerThread sHandlerThread;
+    private static final int NOTE_OP_BATCHING_DELAY_MILLIS = 1000;
+
+    private boolean isNoteOpBatchingSupported() {
+        // If noteOp is called from system server no IPC is made, hence we don't need batching.
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            return false;
+        }
+        return Flags.noteOpBatchingEnabled();
+    }
+
+    private static final Object sBatchedNoteOpLock = new Object();
+    @GuardedBy("sBatchedNoteOpLock")
+    private static boolean sIsBatchedNoteOpCallScheduled = false;
+
     /** Current {@link OnOpNotedCallback}. Change via {@link #setOnOpNotedCallback} */
     @GuardedBy("sLock")
     private static @Nullable OnOpNotedCallback sOnOpNotedCallback;
@@ -2797,7 +2814,7 @@
             .setDefaultMode(AppOpsManager.MODE_ALLOWED)
             .build(),
         new AppOpInfo.Builder(OP_TAKE_AUDIO_FOCUS, OPSTR_TAKE_AUDIO_FOCUS, "TAKE_AUDIO_FOCUS")
-            .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
+            .setDefaultMode(AppOpsManager.MODE_FOREGROUND).build(),
         new AppOpInfo.Builder(OP_AUDIO_MASTER_VOLUME, OPSTR_AUDIO_MASTER_VOLUME,
                 "AUDIO_MASTER_VOLUME").setSwitchCode(OP_AUDIO_MASTER_VOLUME)
             .setRestriction(UserManager.DISALLOW_ADJUST_VOLUME)
@@ -3360,10 +3377,6 @@
      * @hide
      */
     public static @Mode int opToDefaultMode(int op) {
-        if (op == OP_TAKE_AUDIO_FOCUS && roForegroundAudioControl()) {
-            // when removing the flag, change the entry in sAppOpInfos for OP_TAKE_AUDIO_FOCUS
-            return AppOpsManager.MODE_FOREGROUND;
-        }
         return sAppOpInfos[op].defaultMode;
     }
 
@@ -7466,6 +7479,141 @@
     }
 
     /**
+     * A NotedOp is an app op grouped in noteOp API and sent to the system server in a batch
+     *
+     * @hide
+     */
+    public static final class NotedOp implements Parcelable {
+        private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
+        private final @IntRange(from = 0) int mUid;
+        private final @Nullable String mPackageName;
+        private final @Nullable String mAttributionTag;
+        private final int mVirtualDeviceId;
+        private final @Nullable String mMessage;
+        private final boolean mShouldCollectAsyncNotedOp;
+        private final boolean mShouldCollectMessage;
+
+        public NotedOp(int op, int uid, @Nullable String packageName,
+                @Nullable String attributionTag, int virtualDeviceId, @Nullable String message,
+                boolean shouldCollectAsyncNotedOp, boolean shouldCollectMessage) {
+            mOp = op;
+            mUid = uid;
+            mPackageName = packageName;
+            mAttributionTag = attributionTag;
+            mVirtualDeviceId = virtualDeviceId;
+            mMessage = message;
+            mShouldCollectAsyncNotedOp = shouldCollectAsyncNotedOp;
+            mShouldCollectMessage = shouldCollectMessage;
+        }
+
+        NotedOp(Parcel source) {
+            mOp = source.readInt();
+            mUid = source.readInt();
+            mPackageName = source.readString();
+            mAttributionTag = source.readString();
+            mVirtualDeviceId = source.readInt();
+            mMessage = source.readString();
+            mShouldCollectAsyncNotedOp = source.readBoolean();
+            mShouldCollectMessage = source.readBoolean();
+        }
+
+        public int getOp() {
+            return mOp;
+        }
+
+        public int getUid() {
+            return mUid;
+        }
+
+        public @Nullable String getPackageName() {
+            return mPackageName;
+        }
+
+        public @Nullable String getAttributionTag() {
+            return mAttributionTag;
+        }
+
+        public int getVirtualDeviceId() {
+            return mVirtualDeviceId;
+        }
+
+        public @Nullable String getMessage() {
+            return mMessage;
+        }
+
+        public boolean getShouldCollectAsyncNotedOp() {
+            return mShouldCollectAsyncNotedOp;
+        }
+
+        public boolean getShouldCollectMessage() {
+            return mShouldCollectMessage;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeInt(mOp);
+            dest.writeInt(mUid);
+            dest.writeString(mPackageName);
+            dest.writeString(mAttributionTag);
+            dest.writeInt(mVirtualDeviceId);
+            dest.writeString(mMessage);
+            dest.writeBoolean(mShouldCollectAsyncNotedOp);
+            dest.writeBoolean(mShouldCollectMessage);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            NotedOp that = (NotedOp) o;
+            return mOp == that.mOp
+                    && mUid == that.mUid
+                    && Objects.equals(mPackageName, that.mPackageName)
+                    && Objects.equals(mAttributionTag, that.mAttributionTag)
+                    && mVirtualDeviceId == that.mVirtualDeviceId
+                    && Objects.equals(mMessage, that.mMessage)
+                    && Objects.equals(mShouldCollectAsyncNotedOp, that.mShouldCollectAsyncNotedOp)
+                    && Objects.equals(mShouldCollectMessage, that.mShouldCollectMessage);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mOp, mUid, mPackageName, mAttributionTag, mVirtualDeviceId,
+                    mMessage, mShouldCollectAsyncNotedOp, mShouldCollectMessage);
+        }
+
+        @Override
+        public String toString() {
+            return "NotedOp{"
+                    + "mOp=" + mOp
+                    + ", mUid=" + mUid
+                    + ", mPackageName=" + mPackageName
+                    + ", mAttributionTag=" + mAttributionTag
+                    + ", mVirtualDeviceId=" + mVirtualDeviceId
+                    + ", mMessage=" + mMessage
+                    + ", mShouldCollectAsyncNotedOp=" + mShouldCollectAsyncNotedOp
+                    + ", mShouldCollectMessage=" + mShouldCollectMessage
+                    + "}";
+        }
+
+        public static final @NonNull Creator<NotedOp> CREATOR =
+                new Creator<>() {
+                    @Override public NotedOp createFromParcel(Parcel source) {
+                        return new NotedOp(source);
+                    }
+
+                    @Override public NotedOp[] newArray(int size) {
+                        return new NotedOp[size];
+                    }
+                };
+    }
+
+    /**
      * Computes the sum of the counts for the given flags in between the begin and
      * end UID states.
      *
@@ -9301,6 +9449,65 @@
                 message);
     }
 
+    /**
+     * Create a new NotedOp object to represent the note operation. If the note operation is
+     * a duplicate in the buffer, put it in a batch for an async binder call to the system server.
+     *
+     * @return whether this note operation is a duplicate in the buffer. If it's the
+     * first, the noteOp is not batched, the caller should manually call noteOperation.
+     */
+    private boolean batchDuplicateNoteOps(int op, int uid, @Nullable String packageName,
+            @Nullable String attributionTag, int virtualDeviceId, @Nullable String message,
+            boolean collectAsync, boolean shouldCollectMessage) {
+        synchronized (sBatchedNoteOpLock) {
+            NotedOp notedOp = new NotedOp(op, uid, packageName, attributionTag,
+                    virtualDeviceId, message, collectAsync, shouldCollectMessage);
+
+            // Batch same noteOp calls and send them with their counters to the system
+            // service asynchronously. The time window for batching is specified in
+            // NOTE_OP_BATCHING_DELAY_MILLIS. Always allow the first noteOp call to go
+            // through binder API. Accumulate subsequent same noteOp calls during the
+            // time window in sPendingNotedOps.
+            boolean isDuplicated = sPendingNotedOps.containsKey(notedOp);
+            if (!isDuplicated) {
+                sPendingNotedOps.put(notedOp, 0);
+            } else {
+                sPendingNotedOps.merge(notedOp, 1, Integer::sum);
+            }
+
+            if (!sIsBatchedNoteOpCallScheduled) {
+                if (sHandlerThread == null) {
+                    sHandlerThread = new HandlerThread("AppOpsManagerNoteOpBatching");
+                    sHandlerThread.start();
+                }
+
+                sHandlerThread.getThreadHandler().postDelayed(() -> {
+                    ArrayMap<NotedOp, Integer> pendingNotedOpsCopy;
+                    synchronized(sBatchedNoteOpLock) {
+                        sIsBatchedNoteOpCallScheduled = false;
+                        pendingNotedOpsCopy = sPendingNotedOps;
+                        sPendingNotedOps = new ArrayMap<>();
+                    }
+                    for (int i = pendingNotedOpsCopy.size() - 1; i >= 0; i--) {
+                        if (pendingNotedOpsCopy.valueAt(i) == 0) {
+                            pendingNotedOpsCopy.removeAt(i);
+                        }
+                    }
+                    if (!pendingNotedOpsCopy.isEmpty()) {
+                        try {
+                            mService.noteOperationsInBatch(pendingNotedOpsCopy);
+                        } catch (RemoteException e) {
+                            throw e.rethrowFromSystemServer();
+                        }
+                    }
+                }, NOTE_OP_BATCHING_DELAY_MILLIS);
+
+                sIsBatchedNoteOpCallScheduled = true;
+            }
+            return isDuplicated;
+        }
+    }
+
     private int noteOpNoThrow(int op, int uid, @Nullable String packageName,
             @Nullable String attributionTag, int virtualDeviceId, @Nullable String message) {
         try {
@@ -9315,15 +9522,34 @@
                 }
             }
 
-            SyncNotedAppOp syncOp;
-            if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
-                syncOp = mService.noteOperation(op, uid, packageName, attributionTag,
-                        collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
-            } else {
-                syncOp = mService.noteOperationForDevice(op, uid, packageName, attributionTag,
-                    virtualDeviceId, collectionMode == COLLECT_ASYNC, message,
-                    shouldCollectMessage);
+            SyncNotedAppOp syncOp = null;
+            boolean isNoteOpDuplicated = false;
+            if (isNoteOpBatchingSupported()) {
+                int mode = sAppOpModeCache.query(
+                        new AppOpModeQuery(op, uid, packageName, virtualDeviceId, attributionTag,
+                                "noteOpNoThrow"));
+                // For FOREGROUND mode, we still need to make a binder call to the system service
+                // to translate it to ALLOWED or IGNORED. So no batching is needed.
+                if (mode != MODE_FOREGROUND) {
+                    isNoteOpDuplicated = batchDuplicateNoteOps(op, uid, packageName, attributionTag,
+                            virtualDeviceId, message,
+                            collectionMode == COLLECT_ASYNC, shouldCollectMessage);
+
+                    syncOp = new SyncNotedAppOp(mode, op, attributionTag, packageName);
+                }
             }
+
+            if (!isNoteOpDuplicated) {
+                if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
+                    syncOp = mService.noteOperation(op, uid, packageName, attributionTag,
+                            collectionMode == COLLECT_ASYNC, message, shouldCollectMessage);
+                } else {
+                    syncOp = mService.noteOperationForDevice(op, uid, packageName, attributionTag,
+                            virtualDeviceId, collectionMode == COLLECT_ASYNC, message,
+                            shouldCollectMessage);
+                }
+            }
+
             if (syncOp.getOpMode() == MODE_ALLOWED) {
                 if (collectionMode == COLLECT_SELF) {
                     collectNotedOpForSelf(syncOp);
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index b21defb..8b7ea0f 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -29,7 +29,7 @@
 import com.android.internal.util.function.DodecFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
-import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.NonaFunction;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.UndecFunction;
 
@@ -86,9 +86,9 @@
          */
         SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName,
                 @Nullable String featureId, int virtualDeviceId, boolean shouldCollectAsyncNotedOp,
-                @Nullable String message, boolean shouldCollectMessage,
-                @NonNull OctFunction<Integer, Integer, String, String, Integer, Boolean, String,
-                        Boolean, SyncNotedAppOp> superImpl);
+                @Nullable String message, boolean shouldCollectMessage, int notedCount,
+                @NonNull NonaFunction<Integer, Integer, String, String, Integer, Boolean, String,
+                        Boolean, Integer, SyncNotedAppOp> superImpl);
 
         /**
          * Allows overriding note proxy operation behavior.
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index da33847..2dead56 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1751,6 +1751,19 @@
         }
     }
 
+    /** @hide **/
+    @Override
+    public ProviderInfo resolveContentProviderForUid(@NonNull String authority,
+            ComponentInfoFlags flags, int callingUid) {
+        try {
+            return mPM.resolveContentProviderForUid(authority,
+                updateFlagsForComponent(flags.getValue(), getUserId(), null), getUserId(),
+                callingUid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     @Override
     public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
         return queryContentProviders(processName, uid, ComponentInfoFlags.of(flags));
diff --git a/core/java/android/app/BackgroundStartPrivileges.java b/core/java/android/app/BackgroundStartPrivileges.java
index 20278ea..adea0a8 100644
--- a/core/java/android/app/BackgroundStartPrivileges.java
+++ b/core/java/android/app/BackgroundStartPrivileges.java
@@ -23,12 +23,13 @@
 import com.android.internal.util.Preconditions;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Privileges granted to a Process that allows it to execute starts from the background.
  * @hide
  */
-public class BackgroundStartPrivileges {
+public final class BackgroundStartPrivileges {
     /** No privileges. */
     public static final BackgroundStartPrivileges NONE = new BackgroundStartPrivileges(
             false, false, null);
@@ -190,4 +191,22 @@
                 + ", originatingToken=" + mOriginatingToken
                 + ']';
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        BackgroundStartPrivileges that = (BackgroundStartPrivileges) o;
+        return mAllowsBackgroundActivityStarts == that.mAllowsBackgroundActivityStarts
+                && mAllowsBackgroundForegroundServiceStarts
+                == that.mAllowsBackgroundForegroundServiceStarts
+                && Objects.equals(mOriginatingToken, that.mOriginatingToken);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mAllowsBackgroundActivityStarts,
+                mAllowsBackgroundForegroundServiceStarts,
+                mOriginatingToken);
+    }
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 17638ee..8ffea23 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6453,6 +6453,13 @@
             big.setColorStateList(R.id.snooze_button, "setImageTintList", actionColor);
             big.setColorStateList(R.id.bubble_button, "setImageTintList", actionColor);
 
+            if (Flags.notificationsRedesignTemplates()) {
+                int margin = getContentMarginTop(mContext,
+                        R.dimen.notification_2025_content_margin_top);
+                big.setViewLayoutMargin(R.id.notification_main_column, RemoteViews.MARGIN_TOP,
+                        margin, TypedValue.COMPLEX_UNIT_PX);
+            }
+
             boolean validRemoteInput = false;
 
             // In the UI, contextual actions appear separately from the standard actions, so we
@@ -6549,6 +6556,30 @@
             return big;
         }
 
+        /**
+         * Calculate the top margin for the content in px, to allow enough space for the top line
+         * above, using the given resource ID for the desired spacing.
+         *
+         * @hide
+         */
+        public static int getContentMarginTop(Context context, @DimenRes int spacingRes) {
+            final Resources resources = context.getResources();
+            // The margin above the text, at the top of the notification (originally in dp)
+            int notifMargin = resources.getDimensionPixelSize(R.dimen.notification_2025_margin);
+            // Spacing between the text lines, scaling with the font size (originally in sp)
+            int spacing = resources.getDimensionPixelSize(spacingRes);
+
+            // Size of the text in the notification top line (originally in sp)
+            int[] textSizeAttr = new int[] { android.R.attr.textSize };
+            TypedArray typedArray = context.obtainStyledAttributes(
+                    R.style.TextAppearance_DeviceDefault_Notification_Info, textSizeAttr);
+            int textSize = typedArray.getDimensionPixelSize(0 /* index */, -1 /* default */);
+            typedArray.recycle();
+
+            // Adding up all the values as pixels
+            return notifMargin + spacing + textSize;
+        }
+
         private boolean hasValidRemoteInput(Action action) {
             if (TextUtils.isEmpty(action.title) || action.actionIntent == null) {
                 // Weird actions
@@ -11208,8 +11239,8 @@
         private static final String KEY_SEGMENT_LENGTH = "length";
         private static final String KEY_POINT_POSITION = "position";
 
-        private static final int MAX_PROGRESS_SEGMENT_LIMIT = 15;
-        private static final int MAX_PROGRESS_STOP_LIMIT = 5;
+        private static final int MAX_PROGRESS_SEGMENT_LIMIT = 10;
+        private static final int MAX_PROGRESS_POINT_LIMIT = 4;
         private static final int DEFAULT_PROGRESS_MAX = 100;
 
         private List<Segment> mProgressSegments = new ArrayList<>();
@@ -11286,7 +11317,9 @@
                 mProgressSegments = new ArrayList<>();
             }
             mProgressSegments.clear();
-            mProgressSegments.addAll(progressSegments);
+            for (Segment segment : progressSegments) {
+                addProgressSegment(segment);
+            }
             return this;
         }
 
@@ -11302,7 +11335,11 @@
             if (mProgressSegments == null) {
                 mProgressSegments = new ArrayList<>();
             }
-            mProgressSegments.add(segment);
+            if (segment.getLength() > 0) {
+                mProgressSegments.add(segment);
+            } else {
+                Log.w(TAG, "Dropped the segment. The length is not a positive integer.");
+            }
 
             return this;
         }
@@ -11327,7 +11364,14 @@
          * @see Point
          */
         public @NonNull ProgressStyle setProgressPoints(@NonNull List<Point> points) {
-            mProgressPoints = new ArrayList<>(points);
+            if (mProgressPoints == null) {
+                mProgressPoints = new ArrayList<>();
+            }
+            mProgressPoints.clear();
+
+            for (Point point: points) {
+                addProgressPoint(point);
+            }
             return this;
         }
 
@@ -11348,7 +11392,17 @@
             if (mProgressPoints == null) {
                 mProgressPoints = new ArrayList<>();
             }
-            mProgressPoints.add(point);
+            if (point.getPosition() >= 0) {
+                mProgressPoints.add(point);
+
+                if (mProgressPoints.size() > MAX_PROGRESS_POINT_LIMIT) {
+                    Log.w(TAG, "Progress points limit is reached. First"
+                            + MAX_PROGRESS_POINT_LIMIT + " points will be rendered.");
+                }
+
+            } else {
+                Log.w(TAG, "Dropped the point. The position is a negative integer.");
+            }
 
             return this;
         }
@@ -11384,8 +11438,7 @@
             } else {
                 int progressMax = 0;
                 int validSegmentCount = 0;
-                for (int i = 0; i < progressSegment.size()
-                        && validSegmentCount < MAX_PROGRESS_SEGMENT_LIMIT; i++) {
+                for (int i = 0; i < progressSegment.size(); i++) {
                     int segmentLength = progressSegment.get(i).getLength();
                     if (segmentLength > 0) {
                         try {
@@ -11832,6 +11885,30 @@
                     totalLength = DEFAULT_PROGRESS_MAX;
                     segments.add(sanitizeSegment(new Segment(totalLength), backgroundColor,
                             defaultProgressColor));
+                } else if (segments.size() > MAX_PROGRESS_SEGMENT_LIMIT) {
+                    // If segment limit is exceeded. All segments will be replaced
+                    // with a single segment
+                    boolean allSameColor = true;
+                    int firstSegmentColor = segments.get(0).getColor();
+
+                    for (int i = 1; i < segments.size(); i++) {
+                        if (segments.get(i).getColor() != firstSegmentColor) {
+                            allSameColor = false;
+                            break;
+                        }
+                    }
+
+                    // This single segment length has same max as total.
+                    final Segment singleSegment = new Segment(totalLength);
+                    // Single segment color: if all segments have the same color,
+                    // use that color. Otherwise, use 0 / default.
+                    singleSegment.setColor(allSameColor ? firstSegmentColor
+                            : Notification.COLOR_DEFAULT);
+
+                    segments.clear();
+                    segments.add(sanitizeSegment(singleSegment,
+                            backgroundColor,
+                            defaultProgressColor));
                 }
 
                 // Ensure point color contrasts.
@@ -11840,6 +11917,9 @@
                     final int position = point.getPosition();
                     if (position < 0 || position > totalLength) continue;
                     points.add(sanitizePoint(point, backgroundColor, defaultProgressColor));
+                    if (points.size() == MAX_PROGRESS_POINT_LIMIT) {
+                        break;
+                    }
                 }
 
                 model = new NotificationProgressModel(segments, points,
@@ -11868,8 +11948,10 @@
          * has the same hue as the original color, but is lightened or darkened depending on
          * whether the background is dark or light.
          *
+         * @hide
          */
-        private int sanitizeProgressColor(@ColorInt int color,
+        @VisibleForTesting
+        public static int sanitizeProgressColor(@ColorInt int color,
                 @ColorInt int bg,
                 @ColorInt int defaultColor) {
             return Builder.ensureColorContrast(
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 8ed66eb..ec10913 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -55,6 +55,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -67,6 +68,7 @@
 import android.service.notification.ZenPolicy;
 import android.util.Log;
 import android.util.LruCache;
+import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
 import java.lang.annotation.Retention;
@@ -645,16 +647,21 @@
      */
     public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500;
 
-    private static final float MAX_NOTIFICATION_ENQUEUE_RATE = 5f;
+    private static final float MAX_NOTIFICATION_UPDATE_RATE = 5f;
+    private static final float MAX_NOTIFICATION_UNNECESSARY_CANCEL_RATE = 5f;
+    private static final int KNOWN_STATUS_ENQUEUED = 1;
+    private static final int KNOWN_STATUS_CANCELLED = 2;
 
     private final Context mContext;
     private final Map<CallNotificationEventListener, CallNotificationEventCallbackStub>
             mCallNotificationEventCallbacks = new HashMap<>();
 
     private final InstantSource mClock;
-    private final RateEstimator mEnqueueRateEstimator = new RateEstimator();
-    private final LruCache<String, Boolean> mEnqueuedNotificationKeys = new LruCache<>(10);
-    private final Object mEnqueueThrottleLock = new Object();
+    private final RateEstimator mUpdateRateEstimator = new RateEstimator();
+    private final RateEstimator mUnnecessaryCancelRateEstimator = new RateEstimator();
+    // Value is KNOWN_STATUS_ENQUEUED/_CANCELLED
+    private final LruCache<NotificationKey, Integer> mKnownNotifications = new LruCache<>(100);
+    private final Object mThrottleLock = new Object();
 
     @UnsupportedAppUsage
     private static INotificationManager sService;
@@ -677,9 +684,14 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
-    public NotificationManager(Context context, InstantSource clock)
+    public NotificationManager(Context context)
     {
+        this(context, SystemClock.elapsedRealtimeClock());
+    }
+
+    /** {@hide} */
+    @UnsupportedAppUsage
+    public NotificationManager(Context context, InstantSource clock) {
         mContext = context;
         mClock = clock;
     }
@@ -756,6 +768,10 @@
         INotificationManager service = service();
         String sender = mContext.getPackageName();
 
+        if (discardNotify(mContext.getUser(), targetPackage, tag, id, notification)) {
+            return;
+        }
+
         try {
             if (localLOGV) Log.v(TAG, sender + ": notify(" + id + ", " + notification + ")");
             service.enqueueNotificationWithTag(targetPackage, sender, tag, id,
@@ -774,7 +790,7 @@
     {
         INotificationManager service = service();
         String pkg = mContext.getPackageName();
-        if (discardNotify(tag, id, notification)) {
+        if (discardNotify(user, pkg, tag, id, notification)) {
             return;
         }
 
@@ -791,32 +807,39 @@
      * Determines whether a {@link #notify} call should be skipped. If the notification is not
      * skipped, updates tracking metadata to use in future decisions.
      */
-    private boolean discardNotify(@Nullable String tag, int id, Notification notification) {
+    private boolean discardNotify(UserHandle user, String pkg, @Nullable String tag, int id,
+            Notification notification) {
         if (notificationClassification()
                 && NotificationChannel.SYSTEM_RESERVED_IDS.contains(notification.getChannelId())) {
             return true;
         }
 
         if (Flags.nmBinderPerfThrottleNotify()) {
-            String key = toEnqueuedNotificationKey(tag, id);
+            NotificationKey key = new NotificationKey(user, pkg, tag, id);
             long now = mClock.millis();
-            synchronized (mEnqueueThrottleLock) {
-                if (mEnqueuedNotificationKeys.get(key) != null
-                        && !notification.hasCompletedProgress()
-                        && mEnqueueRateEstimator.getRate(now) > MAX_NOTIFICATION_ENQUEUE_RATE) {
-                    return true;
+            synchronized (mThrottleLock) {
+                Integer status = mKnownNotifications.get(key);
+                if (status != null && status == KNOWN_STATUS_ENQUEUED
+                        && !notification.hasCompletedProgress()) {
+                    float updateRate = mUpdateRateEstimator.getRate(now);
+                    if (updateRate > MAX_NOTIFICATION_UPDATE_RATE) {
+                        Slog.w(TAG, "Shedding update of " + key
+                                + ", notification update maximum rate exceeded (" + updateRate
+                                + ")");
+                        return true;
+                    }
+                    mUpdateRateEstimator.update(now);
                 }
 
-                mEnqueueRateEstimator.update(now);
-                mEnqueuedNotificationKeys.put(key, Boolean.TRUE);
+                mKnownNotifications.put(key, KNOWN_STATUS_ENQUEUED);
             }
         }
 
         return false;
     }
-    private static String toEnqueuedNotificationKey(@Nullable String tag, int id) {
-        return tag + "," + id;
-    }
+
+    private record NotificationKey(@NonNull UserHandle user, @NonNull String pkg,
+                                   @Nullable String tag, int id) { }
 
     private Notification fixNotification(Notification notification) {
         String pkg = mContext.getPackageName();
@@ -899,6 +922,10 @@
      * @param id An identifier for this notification.
      */
     public void cancelAsPackage(@NonNull String targetPackage, @Nullable String tag, int id) {
+        if (discardCancel(mContext.getUser(), targetPackage, tag, id)) {
+            return;
+        }
+
         INotificationManager service = service();
         try {
             service.cancelNotificationWithTag(targetPackage, mContext.getOpPackageName(),
@@ -914,14 +941,12 @@
     @UnsupportedAppUsage
     public void cancelAsUser(@Nullable String tag, int id, UserHandle user)
     {
-        if (Flags.nmBinderPerfThrottleNotify()) {
-            synchronized (mEnqueueThrottleLock) {
-                mEnqueuedNotificationKeys.remove(toEnqueuedNotificationKey(tag, id));
-            }
+        String pkg = mContext.getPackageName();
+        if (discardCancel(user, pkg, tag, id)) {
+            return;
         }
 
         INotificationManager service = service();
-        String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancel(" + id + ")");
         try {
             service.cancelNotificationWithTag(
@@ -932,19 +957,52 @@
     }
 
     /**
+     * Determines whether a {@link #cancel} call should be skipped. If not skipped, updates tracking
+     * metadata to use in future decisions.
+     */
+    private boolean discardCancel(UserHandle user, String pkg, @Nullable String tag, int id) {
+        if (Flags.nmBinderPerfThrottleNotify()) {
+            NotificationKey key = new NotificationKey(user, pkg, tag, id);
+            long now = mClock.millis();
+            synchronized (mThrottleLock) {
+                Integer status = mKnownNotifications.get(key);
+                if (status != null && status == KNOWN_STATUS_CANCELLED) {
+                    float cancelRate = mUnnecessaryCancelRateEstimator.getRate(now);
+                    if (cancelRate > MAX_NOTIFICATION_UNNECESSARY_CANCEL_RATE) {
+                        Slog.w(TAG, "Shedding cancel of " + key
+                                + ", presumably unnecessary and maximum rate exceeded ("
+                                + cancelRate + ")");
+                        return true;
+                    }
+                    mUnnecessaryCancelRateEstimator.update(now);
+                }
+                mKnownNotifications.put(key, KNOWN_STATUS_CANCELLED);
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Cancel all previously shown notifications. See {@link #cancel} for the
      * detailed behavior.
      */
     public void cancelAll()
     {
+        String pkg = mContext.getPackageName();
+        UserHandle user = mContext.getUser();
+
         if (Flags.nmBinderPerfThrottleNotify()) {
-            synchronized (mEnqueueThrottleLock) {
-                mEnqueuedNotificationKeys.evictAll();
+            synchronized (mThrottleLock) {
+                for (NotificationKey key : mKnownNotifications.snapshot().keySet()) {
+                    if (key.pkg.equals(pkg) && key.user.equals(user)) {
+                        mKnownNotifications.put(key, KNOWN_STATUS_CANCELLED);
+                    }
+                }
             }
         }
 
         INotificationManager service = service();
-        String pkg = mContext.getPackageName();
         if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
         try {
             service.cancelAllNotifications(pkg, mContext.getUserId());
@@ -968,7 +1026,7 @@
     public void setNotificationDelegate(@Nullable String delegate) {
         INotificationManager service = service();
         String pkg = mContext.getPackageName();
-        if (localLOGV) Log.v(TAG, pkg + ": cancelAll()");
+        if (localLOGV) Log.v(TAG, pkg + ": setNotificationDelegate()");
         try {
             service.setNotificationDelegate(pkg, delegate);
         } catch (RemoteException e) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 51d0b18..d66429a 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -77,6 +77,7 @@
 public class ResourcesManager {
     static final String TAG = "ResourcesManager";
     private static final boolean DEBUG = false;
+    public static final String RESOURCE_CACHE_DIR = "/data/resource-cache/";
 
     private static volatile ResourcesManager sResourcesManager;
 
@@ -581,7 +582,7 @@
     }
 
     private static String overlayPathToIdmapPath(String path) {
-        return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
+        return RESOURCE_CACHE_DIR + path.substring(1).replace('/', '@') + "@idmap";
     }
 
     /**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 920b19c..0bbe943 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -17,7 +17,7 @@
 package android.app;
 
 import static android.app.appfunctions.flags.Flags.enableAppFunctionManager;
-import static android.provider.flags.Flags.stageFlagsForBuild;
+import static android.provider.flags.Flags.newStoragePublicApi;
 import static android.server.Flags.removeGameManagerServiceFromWear;
 
 import android.accounts.AccountManager;
@@ -289,7 +289,6 @@
 import com.android.internal.policy.PhoneLayoutInflater;
 import com.android.internal.util.Preconditions;
 
-import java.time.InstantSource;
 import java.util.Map;
 import java.util.Objects;
 
@@ -625,8 +624,8 @@
                                     com.android.internal.R.style.Theme_Dialog,
                                     com.android.internal.R.style.Theme_Holo_Dialog,
                                     com.android.internal.R.style.Theme_DeviceDefault_Dialog,
-                                    com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog)),
-                    InstantSource.system());
+                                    com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog))
+                );
             }});
 
         registerService(Context.PEOPLE_SERVICE, PeopleManager.class,
@@ -1841,7 +1840,7 @@
             VirtualizationFrameworkInitializer.registerServiceWrappers();
             ConnectivityFrameworkInitializerBaklava.registerServiceWrappers();
 
-            if (stageFlagsForBuild()) {
+            if (newStoragePublicApi()) {
                 ConfigInfrastructureFrameworkInitializer.registerServiceWrappers();
             }
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 39c27a1..84d6741 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -17430,12 +17430,17 @@
     }
 
     /**
-     * Removes a manged profile from the device only when called from a managed profile's context
+     * Removes a managed profile from the device.
      *
-     * @param user UserHandle of the profile to be removed
+     * <p>
+     * Removes the managed profile which is specified by the context user
+     * ({@code Context.createContextAsUser()}).
+     * <p>
+     *
      * @return {@code true} when removal of managed profile was successful, {@code false} when
-     * removal was unsuccessful or throws IllegalArgumentException when provided user was not a
+     * removal was unsuccessful or throws IllegalArgumentException when specified user was not a
      * managed profile
+     *
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java b/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
index e527de2..88001fc 100644
--- a/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
+++ b/core/java/android/app/appfunctions/SafeOneTimeExecuteAppFunctionCallback.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.util.Log;
 
 import java.util.Objects;
@@ -40,8 +39,7 @@
 
     @NonNull private final IExecuteAppFunctionCallback mCallback;
 
-    @Nullable
-    private final CompletionCallback mCompletionCallback;
+    @Nullable private final CompletionCallback mCompletionCallback;
 
     private final AtomicLong mExecutionStartTimeAfterBindMillis = new AtomicLong();
 
@@ -49,7 +47,8 @@
         this(callback, /* completionCallback= */ null);
     }
 
-    public SafeOneTimeExecuteAppFunctionCallback(@NonNull IExecuteAppFunctionCallback callback,
+    public SafeOneTimeExecuteAppFunctionCallback(
+            @NonNull IExecuteAppFunctionCallback callback,
             @Nullable CompletionCallback completionCallback) {
         mCallback = Objects.requireNonNull(callback);
         mCompletionCallback = completionCallback;
@@ -64,8 +63,8 @@
         try {
             mCallback.onSuccess(result);
             if (mCompletionCallback != null) {
-                mCompletionCallback.finalizeOnSuccess(result,
-                        mExecutionStartTimeAfterBindMillis.get());
+                mCompletionCallback.finalizeOnSuccess(
+                        result, mExecutionStartTimeAfterBindMillis.get());
             }
         } catch (RemoteException ex) {
             // Failed to notify the other end. Ignore.
@@ -82,8 +81,8 @@
         try {
             mCallback.onError(error);
             if (mCompletionCallback != null) {
-                mCompletionCallback.finalizeOnError(error,
-                        mExecutionStartTimeAfterBindMillis.get());
+                mCompletionCallback.finalizeOnError(
+                        error, mExecutionStartTimeAfterBindMillis.get());
             }
         } catch (RemoteException ex) {
             // Failed to notify the other end. Ignore.
@@ -103,9 +102,10 @@
      * Sets the execution start time of the request. Used to calculate the overhead latency of
      * requests.
      */
-    public void setExecutionStartTimeMillis() {
-        if (!mExecutionStartTimeAfterBindMillis.compareAndSet(0, SystemClock.elapsedRealtime())) {
-            Log.w(TAG, "Ignore subsequent calls to setExecutionStartTimeMillis()");
+    public void setExecutionStartTimeAfterBindMillis(long executionStartTimeAfterBindMillis) {
+        if (!mExecutionStartTimeAfterBindMillis.compareAndSet(
+                0, executionStartTimeAfterBindMillis)) {
+            Log.w(TAG, "Ignore subsequent calls to setExecutionStartTimeAfterBindMillis()");
         }
     }
 
@@ -115,8 +115,8 @@
      */
     public interface CompletionCallback {
         /** Called after {@link IExecuteAppFunctionCallback#onSuccess}. */
-        void finalizeOnSuccess(@NonNull ExecuteAppFunctionResponse result,
-                long executionStartTimeMillis);
+        void finalizeOnSuccess(
+                @NonNull ExecuteAppFunctionResponse result, long executionStartTimeMillis);
 
         /** Called after {@link IExecuteAppFunctionCallback#onError}. */
         void finalizeOnError(@NonNull AppFunctionException error, long executionStartTimeMillis);
diff --git a/core/java/android/app/contextualsearch/ContextualSearchManager.java b/core/java/android/app/contextualsearch/ContextualSearchManager.java
index 3438cc8..ad43f27 100644
--- a/core/java/android/app/contextualsearch/ContextualSearchManager.java
+++ b/core/java/android/app/contextualsearch/ContextualSearchManager.java
@@ -48,7 +48,9 @@
 
     /**
      * Key to get the entrypoint from the extras of the activity launched by contextual search.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_ENTRYPOINT =
             "android.app.contextualsearch.extra.ENTRYPOINT";
@@ -56,14 +58,18 @@
     /**
      * Key to get the flag_secure value from the extras of the activity launched by contextual
      * search. The value will be true if flag_secure is found in any of the visible activities.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_FLAG_SECURE_FOUND =
             "android.app.contextualsearch.extra.FLAG_SECURE_FOUND";
 
     /**
      * Key to get the screenshot from the extras of the activity launched by contextual search.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_SCREENSHOT =
             "android.app.contextualsearch.extra.SCREENSHOT";
@@ -71,7 +77,9 @@
     /**
      * Key to check whether managed profile is visible from the extras of the activity launched by
      * contextual search. The value will be true if any one of the visible apps is managed.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_IS_MANAGED_PROFILE_VISIBLE =
             "android.app.contextualsearch.extra.IS_MANAGED_PROFILE_VISIBLE";
@@ -79,7 +87,9 @@
     /**
      * Key to get the list of visible packages from the extras of the activity launched by
      * contextual search.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_VISIBLE_PACKAGE_NAMES =
             "android.app.contextualsearch.extra.VISIBLE_PACKAGE_NAMES";
@@ -87,7 +97,9 @@
     /**
      * Key to get the time the user made the invocation request, based on
      * {@link SystemClock#uptimeMillis()}.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      *
      * TODO: un-hide in W
      *
@@ -99,11 +111,24 @@
     /**
      * Key to get the binder token from the extras of the activity launched by contextual search.
      * This token is needed to invoke {@link CallbackToken#getContextualSearchState} method.
-     * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
      */
     public static final String EXTRA_TOKEN = "android.app.contextualsearch.extra.TOKEN";
 
     /**
+     * Key to check whether audio is playing when contextual search is invoked.
+     * Only supposed to be used with ACTION_LAUNCH_CONTEXTUAL_SEARCH.
+     *
+     * @see #ACTION_LAUNCH_CONTEXTUAL_SEARCH
+     *
+     * @hide
+     */
+    public static final String EXTRA_IS_AUDIO_PLAYING =
+            "android.app.contextualsearch.extra.IS_AUDIO_PLAYING";
+
+    /**
      * Intent action for contextual search invocation. The app providing the contextual search
      * experience must add this intent filter action to the activity it wants to be launched.
      * <br>
diff --git a/core/java/android/app/contextualsearch/flags.aconfig b/core/java/android/app/contextualsearch/flags.aconfig
index e8cfd79..c19921d 100644
--- a/core/java/android/app/contextualsearch/flags.aconfig
+++ b/core/java/android/app/contextualsearch/flags.aconfig
@@ -8,6 +8,7 @@
   bug: "309689654"
   is_exported: true
 }
+
 flag {
   name: "enable_token_refresh"
   namespace: "machine_learning"
@@ -27,4 +28,11 @@
     namespace: "sysui_integrations"
     description: "Identify live contextual search UI to exclude from contextual search screenshot."
     bug: "372510690"
+}
+
+flag {
+    name: "include_audio_playing_status"
+    namespace: "sysui_integrations"
+    description: "Add audio playing status to the contextual search invocation intent."
+    bug: "372935419"
 }
\ No newline at end of file
diff --git a/core/java/android/app/jank/AppJankStats.java b/core/java/android/app/jank/AppJankStats.java
index eea1d2b..6ef6a44 100644
--- a/core/java/android/app/jank/AppJankStats.java
+++ b/core/java/android/app/jank/AppJankStats.java
@@ -41,7 +41,8 @@
     // The id that has been set for the widget.
     private String mWidgetId;
 
-    // A general category that the widget applies to.
+    // A general category the widget falls into based on the functions it performs or helps
+    // facilitate.
     private String mWidgetCategory;
 
     // The states that the UI elements can report
@@ -53,78 +54,78 @@
     // Total number of frames determined to be janky during the reported state.
     private long mJankyFrames;
 
-    // Histogram of frame duration overruns encoded in predetermined buckets.
-    private FrameOverrunHistogram mFrameOverrunHistogram;
+    // Histogram of relative frame times encoded in predetermined buckets.
+    private RelativeFrameTimeHistogram mRelativeFrameTimeHistogram;
 
 
     /** Used to indicate no widget category has been set. */
-    public static final String WIDGET_CATEGORY_UNSPECIFIED =
-            "widget_category_unspecified";
+    public static final String WIDGET_CATEGORY_UNSPECIFIED = "unspecified";
 
     /** UI elements that facilitate scrolling. */
-    public static final String SCROLL = "scroll";
+    public static final String WIDGET_CATEGORY_SCROLL = "scroll";
 
     /** UI elements that facilitate playing animations. */
-    public static final String ANIMATION = "animation";
+    public static final String WIDGET_CATEGORY_ANIMATION = "animation";
 
     /** UI elements that facilitate media playback. */
-    public static final String MEDIA = "media";
+    public static final String WIDGET_CATEGORY_MEDIA = "media";
 
     /** UI elements that facilitate in-app navigation. */
-    public static final String NAVIGATION = "navigation";
+    public static final String WIDGET_CATEGORY_NAVIGATION = "navigation";
 
     /** UI elements that facilitate displaying, hiding or interacting with keyboard. */
-    public static final String KEYBOARD = "keyboard";
-
-    /** UI elements that facilitate predictive back gesture navigation. */
-    public static final String PREDICTIVE_BACK = "predictive_back";
+    public static final String WIDGET_CATEGORY_KEYBOARD = "keyboard";
 
     /** UI elements that don't fall in one or any of the other categories. */
-    public static final String OTHER = "other";
+    public static final String WIDGET_CATEGORY_OTHER = "other";
 
     /** Used to indicate no widget state has been set. */
-    public static final String WIDGET_STATE_UNSPECIFIED = "widget_state_unspecified";
+    public static final String WIDGET_STATE_UNSPECIFIED = "unspecified";
 
     /** Used to indicate the UI element currently has no state and is idle. */
-    public static final String NONE = "none";
+    public static final String WIDGET_STATE_NONE = "none";
 
     /** Used to indicate the UI element is currently scrolling. */
-    public static final String SCROLLING = "scrolling";
+    public static final String WIDGET_STATE_SCROLLING = "scrolling";
 
     /** Used to indicate the UI element is currently being flung. */
-    public static final String FLINGING = "flinging";
+    public static final String WIDGET_STATE_FLINGING = "flinging";
 
     /** Used to indicate the UI element is currently being swiped. */
-    public static final String SWIPING = "swiping";
+    public static final String WIDGET_STATE_SWIPING = "swiping";
 
     /** Used to indicate the UI element is currently being dragged. */
-    public static final String DRAGGING = "dragging";
+    public static final String WIDGET_STATE_DRAGGING = "dragging";
 
     /** Used to indicate the UI element is currently zooming. */
-    public static final String ZOOMING = "zooming";
+    public static final String WIDGET_STATE_ZOOMING = "zooming";
 
     /** Used to indicate the UI element is currently animating. */
-    public static final String ANIMATING = "animating";
+    public static final String WIDGET_STATE_ANIMATING = "animating";
 
     /** Used to indicate the UI element is currently playing media. */
-    public static final String PLAYBACK = "playback";
+    public static final String WIDGET_STATE_PLAYBACK = "playback";
 
     /** Used to indicate the UI element is currently being tapped on, for example on a keyboard. */
-    public static final String TAPPING = "tapping";
+    public static final String WIDGET_STATE_TAPPING = "tapping";
+
+    /** Used to indicate predictive back navigation is currently being used */
+    public static final String WIDGET_STATE_PREDICTIVE_BACK = "predictive_back";
 
 
     /**
+     * Provide an organized way to group widgets that have similar purposes or perform related
+     * functions.
      * @hide
      */
-    @StringDef(value = {
+    @StringDef(prefix = {"WIDGET_CATEGORY_"}, value = {
             WIDGET_CATEGORY_UNSPECIFIED,
-            SCROLL,
-            ANIMATION,
-            MEDIA,
-            NAVIGATION,
-            KEYBOARD,
-            PREDICTIVE_BACK,
-            OTHER
+            WIDGET_CATEGORY_SCROLL,
+            WIDGET_CATEGORY_ANIMATION,
+            WIDGET_CATEGORY_MEDIA,
+            WIDGET_CATEGORY_NAVIGATION,
+            WIDGET_CATEGORY_KEYBOARD,
+            WIDGET_CATEGORY_OTHER
     })
     @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
     @Retention(RetentionPolicy.SOURCE)
@@ -133,17 +134,18 @@
     /**
      * @hide
      */
-    @StringDef(value = {
+    @StringDef(prefix = {"WIDGET_STATE_"}, value = {
             WIDGET_STATE_UNSPECIFIED,
-            NONE,
-            SCROLLING,
-            FLINGING,
-            SWIPING,
-            DRAGGING,
-            ZOOMING,
-            ANIMATING,
-            PLAYBACK,
-            TAPPING,
+            WIDGET_STATE_NONE,
+            WIDGET_STATE_SCROLLING,
+            WIDGET_STATE_FLINGING,
+            WIDGET_STATE_SWIPING,
+            WIDGET_STATE_DRAGGING,
+            WIDGET_STATE_ZOOMING,
+            WIDGET_STATE_ANIMATING,
+            WIDGET_STATE_PLAYBACK,
+            WIDGET_STATE_TAPPING,
+            WIDGET_STATE_PREDICTIVE_BACK
     })
     @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
     @Retention(RetentionPolicy.SOURCE)
@@ -156,31 +158,33 @@
      *
      * @param appUid the Uid of the App that is collecting jank stats.
      * @param widgetId the widget id that frames will be associated to.
-     * @param widgetCategory a general functionality category that the widget falls into. Must be
-     *                       one of the following: SCROLL, ANIMATION, MEDIA, NAVIGATION, KEYBOARD,
-     *                       PREDICTIVE_BACK, OTHER or will be set to WIDGET_CATEGORY_UNSPECIFIED
-     *                       if no value is passed.
-     * @param widgetState the state the widget was in while frames were counted. Must be one of
-     *                    the following: NONE, SCROLLING, FLINGING, SWIPING, DRAGGING, ZOOMING,
-     *                    ANIMATING, PLAYBACK, TAPPING or will be set to WIDGET_STATE_UNSPECIFIED
-     *                    if no value is passed.
+     * @param widgetCategory a category used to organize widgets in a structured way that indicates
+     *                       they serve a similar purpose or perform related functions. Must be
+     *                       prefixed with WIDGET_CATEGORY_ and have a suffix of one of the
+     *                       following:SCROLL, ANIMATION, MEDIA, NAVIGATION, KEYBOARD, OTHER or
+     *                       will be set to UNSPECIFIED if no value is passed.
+     * @param widgetState the state the widget was in while frames were counted. Must be prefixed
+     *                    with WIDGET_STATE_ and have a suffix of one of the following:
+     *                    NONE, SCROLLING, FLINGING, SWIPING, DRAGGING, ZOOMING, ANIMATING,
+     *                    PLAYBACK, TAPPING, PREDICTIVE_BACK or will be set to
+     *                    WIDGET_STATE_UNSPECIFIED if no value is passed.
      * @param totalFrames the total number of frames that were counted for this stat.
      * @param jankyFrames the total number of janky frames that were counted for this stat.
-     * @param frameOverrunHistogram the histogram with predefined buckets. See
-     * {@link #getFrameOverrunHistogram()} for details.
+     * @param relativeFrameTimeHistogram the histogram with predefined buckets. See
+     * {@link #getRelativeFrameTimeHistogram()} for details.
      *
      */
     public AppJankStats(int appUid, @NonNull String widgetId,
             @Nullable @WidgetCategory String widgetCategory,
             @Nullable @WidgetState String widgetState, long totalFrames, long jankyFrames,
-            @NonNull FrameOverrunHistogram frameOverrunHistogram) {
+            @NonNull RelativeFrameTimeHistogram relativeFrameTimeHistogram) {
         mUid = appUid;
         mWidgetId = widgetId;
         mWidgetCategory = widgetCategory != null ? widgetCategory : WIDGET_CATEGORY_UNSPECIFIED;
         mWidgetState = widgetState != null ? widgetState : WIDGET_STATE_UNSPECIFIED;
         mTotalFrames = totalFrames;
         mJankyFrames = jankyFrames;
-        mFrameOverrunHistogram = frameOverrunHistogram;
+        mRelativeFrameTimeHistogram = relativeFrameTimeHistogram;
     }
 
     /**
@@ -203,7 +207,7 @@
 
     /**
      * Returns the category that the widget's functionality generally falls into, or
-     * widget_category_unspecified {@link #WIDGET_CATEGORY_UNSPECIFIED} if no value was passed in.
+     * {@link #WIDGET_CATEGORY_UNSPECIFIED} if no value was passed in.
      *
      * @return the category that the widget's functionality generally falls into, this value cannot
      * be null.
@@ -213,7 +217,7 @@
     }
 
     /**
-     * Returns the widget's state that was reported for this stat, or widget_state_unspecified
+     * Returns the widget's state that was reported for this stat, or
      * {@link #WIDGET_STATE_UNSPECIFIED} if no value was passed in.
      *
      * @return the widget's state that was reported for this stat. This value cannot be null.
@@ -241,13 +245,13 @@
     }
 
     /**
-     * Returns a Histogram containing frame overrun times in millis grouped into predefined buckets.
-     * See {@link FrameOverrunHistogram} for more information.
+     * Returns a Histogram containing relative frame times in millis grouped into predefined
+     * buckets. See {@link RelativeFrameTimeHistogram} for more information.
      *
-     * @return Histogram containing frame overrun times in predefined buckets. This value cannot
+     * @return Histogram containing relative frame times in predefined buckets. This value cannot
      * be null.
      */
-    public @NonNull FrameOverrunHistogram getFrameOverrunHistogram() {
-        return mFrameOverrunHistogram;
+    public @NonNull RelativeFrameTimeHistogram getRelativeFrameTimeHistogram() {
+        return mRelativeFrameTimeHistogram;
     }
 }
diff --git a/core/java/android/app/jank/FrameOverrunHistogram.java b/core/java/android/app/jank/FrameOverrunHistogram.java
deleted file mode 100644
index 3ad6531..0000000
--- a/core/java/android/app/jank/FrameOverrunHistogram.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.jank;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-
-import java.util.Arrays;
-
-/**
- * This class is intended to be used when reporting {@link AppJankStats} back to the system. It's
- * intended to be used by library widgets to help facilitate the reporting of frame overrun times
- * by adding those times into predefined buckets.
- */
-@FlaggedApi(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
-public class FrameOverrunHistogram {
-    private static int[] sBucketEndpoints = new int[]{
-            Integer.MIN_VALUE, -200, -150, -100, -90, -80, -70, -60, -50, -40, -30, -25, -20, -18,
-            -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 25, 30, 40,
-            50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000
-    };
-    private int[] mBucketCounts;
-
-    /**
-     * Create a new instance of FrameOverrunHistogram.
-     */
-    public FrameOverrunHistogram() {
-        mBucketCounts = new int[sBucketEndpoints.length];
-    }
-
-    /**
-     * Increases the count by one for the bucket representing the frame overrun duration.
-     *
-     * @param frameOverrunMillis frame overrun duration in millis, frame overrun is the difference
-     *                           between a frames deadline and when it was rendered.
-     */
-    public void addFrameOverrunMillis(int frameOverrunMillis) {
-        int countsIndex = getIndexForCountsFromOverrunTime(frameOverrunMillis);
-        mBucketCounts[countsIndex]++;
-    }
-
-    /**
-     * Returns the counts for the all the frame overrun buckets.
-     *
-     * @return an array of integers representing the counts of frame overrun times. This value
-     * cannot be null.
-     */
-    public @NonNull int[] getBucketCounters() {
-        return Arrays.copyOf(mBucketCounts, mBucketCounts.length);
-    }
-
-    /**
-     * Returns the predefined endpoints for the histogram.
-     *
-     * @return array of integers representing the endpoints for the predefined histogram count
-     * buckets. This value cannot be null.
-     */
-    public @NonNull int[] getBucketEndpointsMillis() {
-        return Arrays.copyOf(sBucketEndpoints, sBucketEndpoints.length);
-    }
-
-    // This takes the overrun time and returns what bucket it belongs to in the counters array.
-    private int getIndexForCountsFromOverrunTime(int overrunTime) {
-        if (overrunTime < 20) {
-            if (overrunTime >= -20) {
-                return (overrunTime + 20) / 2 + 12;
-            }
-            if (overrunTime >= -30) {
-                return (overrunTime + 30) / 5 + 10;
-            }
-            if (overrunTime >= -100) {
-                return (overrunTime + 100) / 10 + 3;
-            }
-            if (overrunTime >= -200) {
-                return (overrunTime + 200) / 50 + 1;
-            }
-            return 0;
-        }
-        if (overrunTime < 30) {
-            return (overrunTime - 20) / 5 + 32;
-        }
-        if (overrunTime < 100) {
-            return (overrunTime - 30) / 10 + 34;
-        }
-        if (overrunTime < 200) {
-            return (overrunTime - 50) / 100 + 41;
-        }
-        if (overrunTime < 1000) {
-            return (overrunTime - 200) / 100 + 43;
-        }
-        return sBucketEndpoints.length - 1;
-    }
-}
diff --git a/core/java/android/app/jank/JankDataProcessor.java b/core/java/android/app/jank/JankDataProcessor.java
index c947259..b4c293e 100644
--- a/core/java/android/app/jank/JankDataProcessor.java
+++ b/core/java/android/app/jank/JankDataProcessor.java
@@ -111,7 +111,7 @@
         pendingStat.mTotalFrames += jankStat.getTotalFrameCount();
 
         mergeOverrunHistograms(pendingStat.mFrameOverrunBuckets,
-                jankStat.getFrameOverrunHistogram().getBucketCounters());
+                jankStat.getRelativeFrameTimeHistogram().getBucketCounters());
     }
 
     private void mergeNewStat(String stateKey, String activityName, AppJankStats jankStats) {
@@ -136,7 +136,7 @@
         pendingStat.mJankyFrames = jankStats.getJankyFrameCount();
 
         mergeOverrunHistograms(pendingStat.mFrameOverrunBuckets,
-                jankStats.getFrameOverrunHistogram().getBucketCounters());
+                jankStats.getRelativeFrameTimeHistogram().getBucketCounters());
 
         mPendingJankStats.put(stateKey, pendingStat);
     }
@@ -271,7 +271,8 @@
         private static final int[] sFrameOverrunHistogramBounds =  {
                 Integer.MIN_VALUE, -200, -150, -100, -90, -80, -70, -60, -50, -40, -30, -25, -20,
                 -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 25,
-                30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000
+                30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000,
+                Integer.MAX_VALUE
         };
         private final int[] mFrameOverrunBuckets = new int[sFrameOverrunHistogramBounds.length];
 
@@ -414,7 +415,7 @@
             if (overrunTime < 200) {
                 return (overrunTime - 50) / 100 + 41;
             }
-            if (overrunTime < 1000) {
+            if (overrunTime <= 1000) {
                 return (overrunTime - 200) / 100 + 43;
             }
             return sFrameOverrunHistogramBounds.length - 1;
diff --git a/core/java/android/app/jank/RelativeFrameTimeHistogram.java b/core/java/android/app/jank/RelativeFrameTimeHistogram.java
new file mode 100644
index 0000000..666f90f
--- /dev/null
+++ b/core/java/android/app/jank/RelativeFrameTimeHistogram.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.jank;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+
+import java.util.Arrays;
+
+/**
+ * A histogram of frame times relative to their deadline.
+ *
+ * This class aids in reporting {@link AppJankStats} to the system and is designed for use by
+ * library widgets. It facilitates the recording of frame times in relation to the frame deadline.
+ * The class records the distribution of time remaining until a frame is considered janky or how
+ * janky the frame was.
+ * <p>
+ * A frame's relative frame time value indicates whether it was delivered early, on time, or late.
+ * A negative relative frame time value indicates the frame was delivered early, a value of zero
+ * indicates the frame was delivered on time and a positive value indicates the frame was delivered
+ * late. The values of the endpoints indicate how early or late a frame was delivered.
+ * <p>
+ * The relative frame times are recorded as a histogram: values are
+ * {@link #addRelativeFrameTimeMillis added} to a bucket by increasing the bucket's counter. The
+ * count of frames with a relative frame time between
+ * {@link #getBucketEndpointsMillis bucket endpoints} {@code i} and {@code i+1} can be obtained
+ * through index {@code i} of {@link #getBucketCounters}.
+ *
+ */
+@FlaggedApi(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
+public class RelativeFrameTimeHistogram {
+    private static int[] sBucketEndpoints = new int[]{
+            Integer.MIN_VALUE, -200, -150, -100, -90, -80, -70, -60, -50, -40, -30, -25, -20, -18,
+            -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 25, 30, 40,
+            50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000,
+            Integer.MAX_VALUE
+    };
+    //
+    private int[] mBucketCounts;
+
+    /**
+     * Create a new instance of RelativeFrameTimeHistogram.
+     */
+    public RelativeFrameTimeHistogram() {
+        mBucketCounts = new int[sBucketEndpoints.length - 1];
+    }
+
+    /**
+     * Increases the count by one for the bucket representing the relative frame time.
+     *
+     * @param frameTimeMillis relative frame time in millis, relative frame time is the difference
+     *                           between a frames deadline and when it was rendered.
+     */
+    public void addRelativeFrameTimeMillis(int frameTimeMillis) {
+        int countsIndex = getRelativeFrameTimeBucketIndex(frameTimeMillis);
+        mBucketCounts[countsIndex]++;
+    }
+
+    /**
+     * Returns the counts for the all the relative frame time buckets.
+     *
+     * @return an array of integers representing the counts of relative frame times. This value
+     * cannot be null.
+     */
+    public @NonNull int[] getBucketCounters() {
+        return Arrays.copyOf(mBucketCounts, mBucketCounts.length);
+    }
+
+    /**
+     * Returns the relative frame time endpoints for the histogram.
+     * <p>
+     * Index {@code i} of {@link #getBucketCounters} contains the count of frames that had a
+     * relative frame time between {@code endpoints[i]} (inclusive) and {@code endpoints[i+1]}
+     * (exclusive).
+     *
+     * @return array of integers representing the endpoints for the predefined histogram count
+     * buckets. This value cannot be null.
+     */
+    public @NonNull int[] getBucketEndpointsMillis() {
+        return Arrays.copyOf(sBucketEndpoints, sBucketEndpoints.length);
+    }
+
+    // This takes the relative frame time and returns what bucket it belongs to in the counters
+    // array.
+    private int getRelativeFrameTimeBucketIndex(int relativeFrameTime) {
+        if (relativeFrameTime < 20) {
+            if (relativeFrameTime >= -20) {
+                return (relativeFrameTime + 20) / 2 + 12;
+            }
+            if (relativeFrameTime >= -30) {
+                return (relativeFrameTime + 30) / 5 + 10;
+            }
+            if (relativeFrameTime >= -100) {
+                return (relativeFrameTime + 100) / 10 + 3;
+            }
+            if (relativeFrameTime >= -200) {
+                return (relativeFrameTime + 200) / 50 + 1;
+            }
+            return 0;
+        }
+        if (relativeFrameTime < 30) {
+            return (relativeFrameTime - 20) / 5 + 32;
+        }
+        if (relativeFrameTime < 100) {
+            return (relativeFrameTime - 30) / 10 + 34;
+        }
+        if (relativeFrameTime < 200) {
+            return (relativeFrameTime - 50) / 100 + 41;
+        }
+        if (relativeFrameTime < 1000) {
+            return (relativeFrameTime - 200) / 100 + 43;
+        }
+        return mBucketCounts.length - 1;
+    }
+}
diff --git a/core/java/android/app/performance.aconfig b/core/java/android/app/performance.aconfig
index 238f1cb..2569f7b 100644
--- a/core/java/android/app/performance.aconfig
+++ b/core/java/android/app/performance.aconfig
@@ -32,7 +32,7 @@
      name: "pic_isolated_cache_statistics"
      is_fixed_read_only: true
      description: "Collects statistics for cache UID isolation strategies"
-     bug: "373752556"
+     bug: "379098894"
 }
 
 flag {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9f898b8..e6ddbf4 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -196,6 +196,21 @@
     ProviderInfo resolveContentProvider(String name, long flags, int userId);
 
     /**
+     * Resolve content providers with a given authority, for a specific
+     * callingUid.
+     *
+     * @param authority Authority of the content provider
+     * @param flags Additional option flags to modify the data returned.
+     * @param userId Current user ID
+     * @param callingUid UID of the caller who's access to the content provider
+              is to be checked
+     *
+     *  @return ProviderInfo of the resolved content provider. May return null
+    */
+    ProviderInfo resolveContentProviderForUid(String authority, long flags,
+      int userId, int callingUid);
+
+    /**
      * Retrieve sync information for all content providers.
      *
      * @param outNames Filled in with a list of the root names of the content
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 438a21b..c16582f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -8349,6 +8349,25 @@
     }
 
     /**
+     * Resolve content providers with a given authority, for a specific callingUid.
+     * @param authority Authority of the content provider
+     * @param flags Additional option flags to modify the data returned.
+     * @param callingUid UID of the caller who's access to the content provider is to be checked
+
+     * @return ProviderInfo of the resolved content provider.
+     * @hide
+     */
+    @Nullable
+    @FlaggedApi(android.content.pm.Flags.FLAG_UID_BASED_PROVIDER_LOOKUP)
+    @RequiresPermission(Manifest.permission.RESOLVE_COMPONENT_FOR_UID)
+    @SystemApi
+    public ProviderInfo resolveContentProviderForUid(@NonNull String authority,
+        @NonNull ComponentInfoFlags flags, int callingUid) {
+        throw new UnsupportedOperationException(
+            "resolveContentProviderForUid not implemented in subclass");
+    }
+
+    /**
      * Retrieve content provider information.
      * <p>
      * <em>Note: unlike most other methods, an empty result set is indicated
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 0d219a9..7bba06c 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -152,7 +152,7 @@
     name: "cache_sdk_system_features"
     namespace: "system_performance"
     description: "Feature flag to enable optimized cache for SDK-defined system feature lookups."
-    bug: "375000483"
+    bug: "326623529"
 }
 
 flag {
@@ -375,3 +375,11 @@
     description: "Feature flag to remove the consumption of the hidden module status (ModuleInfo#IsHidden) in the Android source tree."
     bug: "363952383"
 }
+
+flag {
+    name: "uid_based_provider_lookup"
+    is_exported: true
+    namespace: "package_manager_service"
+    bug: "334024639"
+    description: "Feature flag to check whether a given UID can access a content provider"
+}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index bcaceb2..96c7176 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -992,15 +992,24 @@
                     } else {
                         dr = loadXmlDrawable(wrapper, value, id, density, file);
                     }
-                } else if (file.startsWith("frro://")) {
+                } else if (file.startsWith("frro:/")) {
                     Uri uri = Uri.parse(file);
+                    long offset = Long.parseLong(uri.getQueryParameter("offset"));
+                    long size = Long.parseLong(uri.getQueryParameter("size"));
+                    if (offset < 0 || size <= 0) {
+                        throw new NotFoundException("invalid frro parameters");
+                    }
                     File f = new File('/' + uri.getHost() + uri.getPath());
+                    if (!f.getCanonicalPath().startsWith(ResourcesManager.RESOURCE_CACHE_DIR)
+                            || !f.getCanonicalPath().endsWith(".frro") || !f.canRead()) {
+                        throw new NotFoundException("invalid frro path");
+                    }
                     ParcelFileDescriptor pfd = ParcelFileDescriptor.open(f,
                             ParcelFileDescriptor.MODE_READ_ONLY);
                     AssetFileDescriptor afd = new AssetFileDescriptor(
                             pfd,
-                            Long.parseLong(uri.getQueryParameter("offset")),
-                            Long.parseLong(uri.getQueryParameter("size")));
+                            offset,
+                            size);
                     FileInputStream is = afd.createInputStream();
                     dr = decodeImageDrawable(is, wrapper);
                 } else {
diff --git a/core/java/android/credentials/flags.aconfig b/core/java/android/credentials/flags.aconfig
index 9c811fb..2161e10 100644
--- a/core/java/android/credentials/flags.aconfig
+++ b/core/java/android/credentials/flags.aconfig
@@ -13,6 +13,16 @@
 
 flag {
     namespace: "credential_manager"
+    name: "package_update_fix_enabled"
+    description: "Enable fix for removing package from settings if app is updated or component is modified"
+    bug: "384772470"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    namespace: "credential_manager"
     name: "settings_activity_enabled"
     is_exported: true
     description: "Enable the Credential Manager Settings Activity APIs"
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 852f047..9c6b71b 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -417,6 +417,7 @@
      *                                  or if any of the output configurations sets a stream use
      *                                  case different from {@link
      *                                  android.hardware.camera2.CameraCharacteristics#SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT}.
+     * @throws UnsupportedOperationException if the camera has been opened in shared mode
      * @see CameraExtensionCharacteristics#getSupportedExtensions
      * @see CameraExtensionCharacteristics#getExtensionSupportedSizes
      */
@@ -1258,7 +1259,8 @@
      *                                  configurations are empty; or the session configuration
      *                                  executor is invalid;
      *                                  or the output dynamic range combination is
-     *                                  invalid/unsupported.
+     *                                  invalid/unsupported; or the session type is not shared when
+     *                                  camera has been opened in shared mode.
      * @throws CameraAccessException In case the camera device is no longer connected or has
      *                               encountered a fatal error.
      * @see #createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)
@@ -1292,6 +1294,8 @@
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
+     * @throws UnsupportedOperationException if this is not a primary client of a camera opened in
+     *                                       shared mode
      */
     @NonNull
     public abstract CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType)
@@ -1328,6 +1332,8 @@
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
+     * @throws UnsupportedOperationException if this is not a primary client of a camera opened in
+     *                                       shared mode
      *
      * @see #TEMPLATE_PREVIEW
      * @see #TEMPLATE_RECORD
@@ -1369,6 +1375,7 @@
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
+     * @throws UnsupportedOperationException if the camera has been opened in shared mode
      *
      * @see CaptureRequest.Builder
      * @see TotalCaptureResult
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index aba2345..bfaff94 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -1375,6 +1375,9 @@
      * @throws SecurityException if the application does not have permission to
      *                           access the camera
      *
+     * @throws UnsupportedOperationException if {@link #isCameraDeviceSharingSupported} returns
+     *                                       false for the given {@code cameraId}.
+     *
      * @see #getCameraIdList
      * @see android.app.admin.DevicePolicyManager#setCameraDisabled
      *
@@ -1393,6 +1396,10 @@
         if (executor == null) {
             throw new IllegalArgumentException("executor was null");
         }
+        if (!isCameraDeviceSharingSupported(cameraId)) {
+            throw new UnsupportedOperationException(
+                    "CameraDevice sharing is not supported for Camera ID: " + cameraId);
+        }
         openCameraImpl(cameraId, callback, executor, /*oomScoreOffset*/0,
                 getRotationOverride(mContext), /*sharedMode*/true);
     }
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 496d316..1c65b08 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -299,6 +299,24 @@
         return mRequestType;
     }
 
+    /**
+     * Get the stream ids corresponding to the target surfaces.
+     *
+     * @hide
+     */
+    public int[] getStreamIds() {
+        return mStreamIdxArray;
+    };
+
+    /**
+     * Get the surface ids corresponding to the target surfaces.
+     *
+     * @hide
+     */
+    public int[] getSurfaceIds() {
+        return mSurfaceIdxArray;
+    };
+
     // If this request is part of constrained high speed request list that was created by
     // {@link android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList}
     private boolean mIsPartOfCHSRequestList = false;
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index ce8661e..7e0456b 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -340,6 +340,30 @@
         }
     }
 
+    /**
+     * Shared Camera capture session API which can be used by the clients
+     * to start streaming.
+     *
+     * @hide
+     */
+    public int startStreaming(List<Surface> surfaces, Executor executor,
+            CaptureCallback callback) throws CameraAccessException {
+
+        synchronized (mDeviceImpl.mInterfaceLock) {
+            checkNotClosed();
+
+            executor = CameraDeviceImpl.checkExecutor(executor, callback);
+
+            if (DEBUG) {
+                Log.v(TAG, mIdString + "startStreaming callback " + callback + " executor"
+                        + " " + executor);
+            }
+
+            return addPendingSequence(mDeviceImpl.startStreaming(surfaces,
+                    createCaptureCallbackProxyWithExecutor(executor, callback), mDeviceExecutor));
+        }
+    }
+
     private void checkRepeatingRequest(CaptureRequest request) {
         if (request == null) {
             throw new IllegalArgumentException("request must not be null");
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 34c0f7b..89a6b02 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -451,6 +451,16 @@
         }
     }
 
+    /**
+     * When camera device is opened in shared mode, call to check if this is a primary client.
+     *
+     */
+    public boolean isPrimaryClient() {
+        synchronized (mInterfaceLock) {
+            return mIsPrimaryClient;
+        }
+    }
+
     private Map<String, CameraCharacteristics> getPhysicalIdToChars() {
         if (mPhysicalIdsToChars == null) {
             try {
@@ -482,8 +492,19 @@
 
             mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
             Parcel resultParcel = Parcel.obtain();
-            mRemoteDevice.getCaptureResultMetadataQueue().writeToParcel(resultParcel, 0);
+
+            // Passing in PARCELABLE_WRITE_RETURN_VALUE closes the ParcelFileDescriptors
+            // owned by MQDescriptor returned by getCaptureResultMetadataQueue()
+            // Though these will be closed when GC runs, that may not happen for a while.
+            // Also, apps running with StrictMode would get warnings / crash in the case they're not
+            // explicitly closed.
+            mRemoteDevice.getCaptureResultMetadataQueue().writeToParcel(resultParcel,
+                    Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
             mFMQReader = nativeCreateFMQReader(resultParcel);
+            // Recycle since resultParcel would dup fds from MQDescriptor as well. We don't
+            // need them after the native FMQ reader has been created. That is since the native
+            // creates calls MQDescriptor.readFromParcel() which again dups the fds.
+            resultParcel.recycle();
 
             IBinder remoteDeviceBinder = remoteDevice.asBinder();
             // For legacy camera device, remoteDevice is in the same process, and
@@ -847,24 +868,19 @@
         List<SharedOutputConfiguration> sharedConfigs =
                 sharedSessionConfiguration.getOutputStreamsInformation();
         for (SharedOutputConfiguration sharedConfig : sharedConfigs) {
-            if (outConfig.getConfiguredSize().equals(sharedConfig.getSize())
-                    && (outConfig.getConfiguredFormat() == sharedConfig.getFormat())
-                    && (outConfig.getSurfaceGroupId() == OutputConfiguration.SURFACE_GROUP_ID_NONE)
-                    && (outConfig.getSurfaceType() == sharedConfig.getSurfaceType())
+            if ((outConfig.getSurfaceGroupId() == OutputConfiguration.SURFACE_GROUP_ID_NONE)
                     && (outConfig.getMirrorMode() == sharedConfig.getMirrorMode())
-                    && (outConfig.getUsage() == sharedConfig.getUsage())
                     && (outConfig.isReadoutTimestampEnabled()
                     == sharedConfig.isReadoutTimestampEnabled())
                     && (outConfig.getTimestampBase() == sharedConfig.getTimestampBase())
                     && (outConfig.getStreamUseCase() == sharedConfig.getStreamUseCase())
-                    && (outConfig.getColorSpace().equals(
-                    sharedSessionConfiguration.getColorSpace()))
                     && (outConfig.getDynamicRangeProfile()
                     == DynamicRangeProfiles.STANDARD)
-                    && (outConfig.getConfiguredDataspace() == sharedConfig.getDataspace())
                     && (Objects.equals(outConfig.getPhysicalCameraId(),
                     sharedConfig.getPhysicalCameraId()))
                     && (outConfig.getSensorPixelModes().isEmpty())
+                    && (!outConfig.isMultiResolution())
+                    && (!outConfig.isDeferredConfiguration())
                     && (!outConfig.isShared())) {
                 //Found valid config, return true
                 return true;
@@ -896,14 +912,6 @@
         if (config.getExecutor() == null) {
             throw new IllegalArgumentException("Invalid executor");
         }
-        if (mSharedMode) {
-            if (config.getSessionType() != SessionConfiguration.SESSION_SHARED) {
-                throw new IllegalArgumentException("Invalid session type");
-            }
-            if (!checkSharedSessionConfiguration(outputConfigs)) {
-                throw new IllegalArgumentException("Invalid output configurations");
-            }
-        }
         createCaptureSessionInternal(config.getInputConfiguration(), outputConfigs,
                 config.getStateCallback(), config.getExecutor(), config.getSessionType(),
                 config.getSessionParameters());
@@ -921,17 +929,26 @@
 
             checkIfCameraClosedOrInError();
 
+            boolean isSharedSession = (operatingMode == ICameraDeviceUser.SHARED_MODE);
+            if (Flags.cameraMultiClient() && mSharedMode) {
+                if (!isSharedSession) {
+                    throw new IllegalArgumentException("Invalid session type");
+                }
+                if (!checkSharedSessionConfiguration(outputConfigurations)) {
+                    throw new IllegalArgumentException("Invalid output configurations");
+                }
+                if (inputConfig != null) {
+                    throw new IllegalArgumentException("Shared capture session doesn't support"
+                            + " input configuration yet.");
+                }
+            }
+
             boolean isConstrainedHighSpeed =
                     (operatingMode == ICameraDeviceUser.CONSTRAINED_HIGH_SPEED_MODE);
             if (isConstrainedHighSpeed && inputConfig != null) {
                 throw new IllegalArgumentException("Constrained high speed session doesn't support"
                         + " input configuration yet.");
             }
-            boolean isSharedSession = (operatingMode == ICameraDeviceUser.SHARED_MODE);
-            if (isSharedSession && inputConfig != null) {
-                throw new IllegalArgumentException("Shared capture session doesn't support"
-                        + " input configuration yet.");
-            }
 
             if (mCurrentExtensionSession != null) {
                 mCurrentExtensionSession.commitStats();
@@ -993,8 +1010,7 @@
                         mCharacteristics);
             } else if (isSharedSession) {
                 newSession = new CameraSharedCaptureSessionImpl(mNextSessionId++,
-                        callback, executor, this, mDeviceExecutor, configureSuccess,
-                        mIsPrimaryClient);
+                        callback, executor, this, mDeviceExecutor, configureSuccess);
             } else {
                 newSession = new CameraCaptureSessionImpl(mNextSessionId++, input,
                         callback, executor, this, mDeviceExecutor, configureSuccess);
@@ -1063,6 +1079,11 @@
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
 
+            if (Flags.cameraMultiClient() && mSharedMode && !mIsPrimaryClient) {
+                throw new UnsupportedOperationException("In shared session mode,"
+                        + "only primary clients can create capture request.");
+            }
+
             for (String physicalId : physicalCameraIdSet) {
                 if (Objects.equals(physicalId, getId())) {
                     throw new IllegalStateException("Physical id matches the logical id!");
@@ -1089,6 +1110,11 @@
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
 
+            if (Flags.cameraMultiClient() && mSharedMode && !mIsPrimaryClient) {
+                throw new UnsupportedOperationException("In shared session mode,"
+                        + "only primary clients can create capture request.");
+            }
+
             CameraMetadataNative templatedRequest = null;
 
             templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
@@ -1108,6 +1134,10 @@
             throws CameraAccessException {
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
+            if (Flags.cameraMultiClient() && mSharedMode) {
+                throw new UnsupportedOperationException("In shared session mode,"
+                        + "reprocess capture requests are not supported.");
+            }
 
             CameraMetadataNative resultMetadata = new
                     CameraMetadataNative(inputResult.getNativeCopy());
@@ -1561,6 +1591,74 @@
         }
     }
 
+    public int startStreaming(List<Surface> surfaces, CaptureCallback callback,
+            Executor executor) throws CameraAccessException {
+        // Need a valid executor, or current thread needs to have a looper, if
+        // callback is valid
+        executor = checkExecutor(executor, callback);
+        synchronized (mInterfaceLock) {
+            checkIfCameraClosedOrInError();
+            for (Surface surface : surfaces) {
+                if (surface == null) {
+                    throw new IllegalArgumentException("Null Surface targets are not allowed");
+                }
+            }
+            // In shared session mode, if there are other active clients streaming then
+            // stoprepeating does not actually send request to HAL to cancel the request.
+            // Cameraservice will use this call to remove this client surfaces provided in its
+            // previous streaming request. If this is the only client for the shared camera device
+            // then camerservice will ask HAL to cancel the previous repeating request
+            stopRepeating();
+
+            // StartStreaming API does not allow capture parameters to be provided through a capture
+            // request. If the primary client has an existing repeating request, the camera service
+            // will either attach the provided surfaces to that request or create a default capture
+            // request if no repeating request is active. A default capture request is created here
+            // for initial use. The capture callback will provide capture results that include the
+            // actual capture parameters used for the streaming.
+            CaptureRequest.Builder builder = createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+            for (Surface surface : surfaces) {
+                builder.addTarget(surface);
+            }
+            CaptureRequest request = builder.build();
+            request.convertSurfaceToStreamId(mConfiguredOutputs);
+
+            SubmitInfo requestInfo;
+            requestInfo = mRemoteDevice.startStreaming(request.getStreamIds(),
+                    request.getSurfaceIds());
+            request.recoverStreamIdToSurface();
+            List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+            requestList.add(request);
+
+            if (callback != null) {
+                mCaptureCallbackMap.put(requestInfo.getRequestId(),
+                        new CaptureCallbackHolder(
+                            callback, requestList, executor, true, mNextSessionId - 1));
+            } else {
+                if (DEBUG) {
+                    Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
+                }
+            }
+
+            if (mRepeatingRequestId != REQUEST_ID_NONE) {
+                checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId,
+                        requestInfo.getLastFrameNumber(), mRepeatingRequestTypes);
+            }
+
+            CaptureRequest[] requestArray = requestList.toArray(
+                    new CaptureRequest[requestList.size()]);
+            mRepeatingRequestId = requestInfo.getRequestId();
+            mRepeatingRequestTypes = getRequestTypes(requestArray);
+
+            if (mIdle) {
+                mDeviceExecutor.execute(mCallOnActive);
+            }
+            mIdle = false;
+
+            return requestInfo.getRequestId();
+        }
+    }
+
     public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
             Executor executor) throws CameraAccessException {
         List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
@@ -2883,6 +2981,11 @@
     @Override
     public void createExtensionSession(ExtensionSessionConfiguration extensionConfiguration)
             throws CameraAccessException {
+        if (Flags.cameraMultiClient() && mSharedMode) {
+            throw new UnsupportedOperationException("In shared session mode,"
+                    + "extension sessions are not supported.");
+        }
+
         HashMap<String, CameraCharacteristics> characteristicsMap = new HashMap<>(
                 getPhysicalIdToChars());
         characteristicsMap.put(mCameraId, mCharacteristics);
@@ -2918,4 +3021,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraSharedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraSharedCaptureSessionImpl.java
index a1f31c0..8c0dcfb 100644
--- a/core/java/android/hardware/camera2/impl/CameraSharedCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraSharedCaptureSessionImpl.java
@@ -19,6 +19,8 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraOfflineSession;
+import android.hardware.camera2.CameraOfflineSession.CameraOfflineSessionCallback;
 import android.hardware.camera2.CameraSharedCaptureSession;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.params.OutputConfiguration;
@@ -28,6 +30,7 @@
 
 import com.android.internal.camera.flags.Flags;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
@@ -46,7 +49,8 @@
     private static final String TAG = "CameraSharedCaptureSessionImpl";
     private final CameraCaptureSessionImpl mSessionImpl;
     private final ConditionVariable mInitialized = new ConditionVariable();
-    private boolean mIsPrimary;
+    private final android.hardware.camera2.impl.CameraDeviceImpl mCameraDevice;
+    private final Executor mDeviceExecutor;  
 
     /**
      * Create a new CameraCaptureSession.
@@ -54,24 +58,32 @@
     CameraSharedCaptureSessionImpl(int id,
             CameraCaptureSession.StateCallback callback, Executor stateExecutor,
             android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
-            Executor deviceStateExecutor, boolean configureSuccess, boolean isPrimary) {
+            Executor deviceStateExecutor, boolean configureSuccess) {
         CameraCaptureSession.StateCallback wrapperCallback = new WrapperCallback(callback);
         mSessionImpl = new CameraCaptureSessionImpl(id, /*input*/null, wrapperCallback,
                 stateExecutor, deviceImpl, deviceStateExecutor, configureSuccess);
-        mIsPrimary = isPrimary;
+        mCameraDevice = deviceImpl;
+        mDeviceExecutor = deviceStateExecutor;
         mInitialized.open();
     }
 
     @Override
-    public int startStreaming(List<Surface> surfaces, Executor executor, CaptureCallback listener)
+    public int startStreaming(List<Surface> surfaces, Executor executor, CaptureCallback callback)
             throws CameraAccessException {
-        // Todo: Need to add implementation.
-        return 0;
+        if (surfaces.isEmpty()) {
+            throw new IllegalArgumentException("No surfaces provided for streaming");
+        } else if (executor == null) {
+            throw new IllegalArgumentException("executor must not be null");
+        } else if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
+
+        return mSessionImpl.startStreaming(surfaces, executor, callback);
     }
 
     @Override
     public void stopStreaming() throws CameraAccessException {
-      // Todo: Need to add implementation.
+        mSessionImpl.stopRepeating();
     }
 
     @Override
@@ -90,16 +102,24 @@
     }
 
     @Override
+    public boolean supportsOfflineProcessing(Surface surface) {
+        return false;
+    }
+
+    @Override
     public void abortCaptures() throws CameraAccessException {
-        if (mIsPrimary) {
+        if (mCameraDevice.isPrimaryClient()) {
             mSessionImpl.abortCaptures();
+            return;
         }
+        throw new UnsupportedOperationException("Shared capture session only supports this method"
+                + " for primary clients");
     }
 
     @Override
     public int setRepeatingRequest(CaptureRequest request, CaptureCallback listener,
             Handler handler) throws CameraAccessException {
-        if (mIsPrimary) {
+        if (mCameraDevice.isPrimaryClient()) {
             return mSessionImpl.setRepeatingRequest(request, listener, handler);
         }
         throw new UnsupportedOperationException("Shared capture session only supports this method"
@@ -107,16 +127,30 @@
     }
 
     @Override
-    public void stopRepeating() throws CameraAccessException {
-        if (mIsPrimary) {
-            mSessionImpl.stopRepeating();
+    public int setSingleRepeatingRequest(CaptureRequest request, Executor executor,
+            CaptureCallback listener)
+            throws CameraAccessException {
+        if (mCameraDevice.isPrimaryClient()) {
+            return mSessionImpl.setSingleRepeatingRequest(request, executor, listener);
         }
+        throw new UnsupportedOperationException("Shared capture session only supports this method"
+                + " for primary clients");
+    }
+
+    @Override
+    public void stopRepeating() throws CameraAccessException {
+        if (mCameraDevice.isPrimaryClient()) {
+            mSessionImpl.stopRepeating();
+            return;
+        }
+        throw new UnsupportedOperationException("Shared capture session only supports this method"
+                + " for primary clients");
     }
 
     @Override
     public int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
             throws CameraAccessException {
-        if (mIsPrimary) {
+        if (mCameraDevice.isPrimaryClient()) {
             return mSessionImpl.capture(request, listener, handler);
         }
         throw new UnsupportedOperationException("Shared capture session only supports this method"
@@ -124,6 +158,17 @@
     }
 
     @Override
+    public int captureSingleRequest(CaptureRequest request, Executor executor,
+            CaptureCallback listener)
+            throws CameraAccessException {
+        if (mCameraDevice.isPrimaryClient()) {
+            return mSessionImpl.captureSingleRequest(request, executor, listener);
+        }
+        throw new UnsupportedOperationException("Shared capture session only supports this method"
+                + " for primary clients");
+    }
+
+    @Override
     public void tearDown(Surface surface) throws CameraAccessException {
         mSessionImpl.tearDown(surface);
     }
@@ -149,48 +194,72 @@
     }
 
     @Override
+    public CameraOfflineSession switchToOffline(Collection<Surface> offlineSurfaces,
+            Executor executor, CameraOfflineSessionCallback listener)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("Shared capture session do not support this method"
+                );
+    }
+
+    @Override
     public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener,
             Handler handler) throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared Capture session doesn't support"
+        throw new UnsupportedOperationException("Shared Capture session do not support"
+                + " this method");
+    }
+
+    @Override
+    public int setRepeatingBurstRequests(List<CaptureRequest> requests,
+            Executor executor, CaptureCallback listener)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("Shared Capture session do not support"
                 + " this method");
     }
 
     @Override
     public int captureBurst(List<CaptureRequest> requests, CaptureCallback listener,
             Handler handler) throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared Capture session doesn't support"
+        throw new UnsupportedOperationException("Shared Capture session do not support"
+                + " this method");
+    }
+
+    @Override
+    public int captureBurstRequests(List<CaptureRequest> requests,
+            Executor executor, CaptureCallback listener)
+            throws CameraAccessException {
+        throw new UnsupportedOperationException("Shared Capture session do not support"
                 + " this method");
     }
 
     @Override
     public void updateOutputConfiguration(OutputConfiguration config)
             throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared capture session doesn't support"
+        throw new UnsupportedOperationException("Shared capture session do not support"
                 + " this method");
     }
 
     @Override
     public void finalizeOutputConfigurations(List<OutputConfiguration> deferredOutputConfigs)
             throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared capture session doesn't support"
+        throw new UnsupportedOperationException("Shared capture session do not support"
                 + " this method");
     }
 
     @Override
     public void prepare(Surface surface) throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared capture session doesn't support"
+        throw new UnsupportedOperationException("Shared capture session do not support"
                 + " this method");
     }
 
     @Override
     public void prepare(int maxCount, Surface surface) throws CameraAccessException {
-        throw new UnsupportedOperationException("Shared capture session doesn't support"
+        throw new UnsupportedOperationException("Shared capture session do not support"
                 + " this method");
     }
 
     @Override
     public void closeWithoutDraining() {
-        throw new UnsupportedOperationException("Shared capture session doesn't support"
+        throw new UnsupportedOperationException("Shared capture session do not support"
                 + " this method");
     }
 
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index a79e084..0b8e9c2 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -65,6 +65,17 @@
         }
     }
 
+    public SubmitInfo startStreaming(int[] streamIdxArray, int[] surfaceIdxArray)
+            throws CameraAccessException {
+        try {
+            return mRemoteDevice.startStreaming(streamIdxArray, surfaceIdxArray);
+        } catch (ServiceSpecificException e) {
+            throw ExceptionUtils.throwAsPublicException(e);
+        } catch (RemoteException e) {
+            throw ExceptionUtils.throwAsPublicException(e);
+        }
+    }
+
     public SubmitInfo submitRequest(CaptureRequest request, boolean streaming)
             throws CameraAccessException  {
         try {
@@ -325,4 +336,4 @@
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index e12c463..d394154 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -1803,6 +1803,19 @@
     }
 
     /**
+     * Get the flag indicating if this {@link OutputConfiguration} is for a multi-resolution output
+     * with a MultiResolutionImageReader.
+     *
+     * @return true if this {@link OutputConfiguration} is for a multi-resolution output with a
+     *              MultiResolutionImageReader.
+     *
+     * @hide
+     */
+    public boolean isMultiResolution() {
+        return mIsMultiResolution;
+    }
+
+    /**
      * Get the physical camera ID associated with this {@link OutputConfiguration}.
      *
      * <p>If this OutputConfiguration isn't targeting a physical camera of a logical
diff --git a/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java b/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
index cdcc92c..365f870 100644
--- a/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
+++ b/core/java/android/hardware/camera2/params/SharedSessionConfiguration.java
@@ -212,7 +212,7 @@
         }
 
         public @Nullable String getPhysicalCameraId() {
-            return mPhysicalCameraId;
+            return mPhysicalCameraId.isEmpty() ? null : mPhysicalCameraId;
         }
     }
 
diff --git a/core/java/android/hardware/contexthub/HubEndpoint.java b/core/java/android/hardware/contexthub/HubEndpoint.java
index 99f331f..6c669a3 100644
--- a/core/java/android/hardware/contexthub/HubEndpoint.java
+++ b/core/java/android/hardware/contexthub/HubEndpoint.java
@@ -99,8 +99,8 @@
 
     private final Object mLock = new Object();
     private final HubEndpointInfo mPendingHubEndpointInfo;
-    @Nullable private final IHubEndpointLifecycleCallback mLifecycleCallback;
-    @Nullable private final IHubEndpointMessageCallback mMessageCallback;
+    @Nullable private final HubEndpointLifecycleCallback mLifecycleCallback;
+    @Nullable private final HubEndpointMessageCallback mMessageCallback;
     @NonNull private final Executor mLifecycleCallbackExecutor;
     @NonNull private final Executor mMessageCallbackExecutor;
 
@@ -296,7 +296,7 @@
                     }
 
                     if (activeSession == null || mMessageCallback == null) {
-                        if (message.getDeliveryParams().isResponseRequired()) {
+                        if (message.isResponseRequired()) {
                             try {
                                 mServiceToken.sendMessageDeliveryStatus(
                                         sessionId,
@@ -313,7 +313,7 @@
                     mMessageCallbackExecutor.execute(
                             () -> {
                                 mMessageCallback.onMessageReceived(activeSession, message);
-                                if (message.getDeliveryParams().isResponseRequired()) {
+                                if (message.isResponseRequired()) {
                                     try {
                                         mServiceToken.sendMessageDeliveryStatus(
                                                 sessionId,
@@ -335,9 +335,9 @@
 
     private HubEndpoint(
             @NonNull HubEndpointInfo pendingEndpointInfo,
-            @Nullable IHubEndpointLifecycleCallback endpointLifecycleCallback,
+            @Nullable HubEndpointLifecycleCallback endpointLifecycleCallback,
             @NonNull Executor lifecycleCallbackExecutor,
-            @Nullable IHubEndpointMessageCallback endpointMessageCallback,
+            @Nullable HubEndpointMessageCallback endpointMessageCallback,
             @NonNull Executor messageCallbackExecutor) {
         mPendingHubEndpointInfo = pendingEndpointInfo;
         mLifecycleCallback = endpointLifecycleCallback;
@@ -485,12 +485,12 @@
     }
 
     @Nullable
-    public IHubEndpointLifecycleCallback getLifecycleCallback() {
+    public HubEndpointLifecycleCallback getLifecycleCallback() {
         return mLifecycleCallback;
     }
 
     @Nullable
-    public IHubEndpointMessageCallback getMessageCallback() {
+    public HubEndpointMessageCallback getMessageCallback() {
         return mMessageCallback;
     }
 
@@ -498,12 +498,13 @@
     public static final class Builder {
         private final String mPackageName;
 
-        @Nullable private IHubEndpointLifecycleCallback mLifecycleCallback;
+        @Nullable private HubEndpointLifecycleCallback mLifecycleCallback;
+        @Nullable private Executor mLifecycleCallbackExecutor;
 
-        @NonNull private Executor mLifecycleCallbackExecutor;
+        @Nullable private HubEndpointMessageCallback mMessageCallback;
+        @Nullable private Executor mMessageCallbackExecutor;
 
-        @Nullable private IHubEndpointMessageCallback mMessageCallback;
-        @NonNull private Executor mMessageCallbackExecutor;
+        @NonNull private final Executor mMainExecutor;
 
         private int mVersion;
         @Nullable private String mTag;
@@ -514,8 +515,7 @@
         public Builder(@NonNull Context context) {
             mPackageName = context.getPackageName();
             mVersion = (int) context.getApplicationInfo().longVersionCode;
-            mLifecycleCallbackExecutor = context.getMainExecutor();
-            mMessageCallbackExecutor = context.getMainExecutor();
+            mMainExecutor = context.getMainExecutor();
         }
 
         /**
@@ -539,10 +539,14 @@
             return this;
         }
 
-        /** Attach a callback interface for lifecycle events for this Endpoint */
+        /**
+         * Attach a callback interface for lifecycle events for this Endpoint. Callback will be
+         * posted to the main thread.
+         */
         @NonNull
         public Builder setLifecycleCallback(
-                @NonNull IHubEndpointLifecycleCallback lifecycleCallback) {
+                @NonNull HubEndpointLifecycleCallback lifecycleCallback) {
+            mLifecycleCallbackExecutor = null;
             mLifecycleCallback = lifecycleCallback;
             return this;
         }
@@ -554,15 +558,19 @@
         @NonNull
         public Builder setLifecycleCallback(
                 @NonNull @CallbackExecutor Executor executor,
-                @NonNull IHubEndpointLifecycleCallback lifecycleCallback) {
+                @NonNull HubEndpointLifecycleCallback lifecycleCallback) {
             mLifecycleCallbackExecutor = executor;
             mLifecycleCallback = lifecycleCallback;
             return this;
         }
 
-        /** Attach a callback interface for message events for this Endpoint */
+        /**
+         * Attach a callback interface for message events for this Endpoint. Callback will be posted
+         * to the main thread.
+         */
         @NonNull
-        public Builder setMessageCallback(@NonNull IHubEndpointMessageCallback messageCallback) {
+        public Builder setMessageCallback(@NonNull HubEndpointMessageCallback messageCallback) {
+            mMessageCallbackExecutor = null;
             mMessageCallback = messageCallback;
             return this;
         }
@@ -574,7 +582,7 @@
         @NonNull
         public Builder setMessageCallback(
                 @NonNull @CallbackExecutor Executor executor,
-                @NonNull IHubEndpointMessageCallback messageCallback) {
+                @NonNull HubEndpointMessageCallback messageCallback) {
             mMessageCallbackExecutor = executor;
             mMessageCallback = messageCallback;
             return this;
@@ -598,9 +606,9 @@
             return new HubEndpoint(
                     new HubEndpointInfo(mPackageName, mVersion, mTag, mServiceInfos),
                     mLifecycleCallback,
-                    mLifecycleCallbackExecutor,
+                    mLifecycleCallbackExecutor != null ? mLifecycleCallbackExecutor : mMainExecutor,
                     mMessageCallback,
-                    mMessageCallbackExecutor);
+                    mMessageCallbackExecutor != null ? mMessageCallbackExecutor : mMainExecutor);
         }
     }
 }
diff --git a/core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java b/core/java/android/hardware/contexthub/HubEndpointDiscoveryCallback.java
similarity index 96%
rename from core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java
rename to core/java/android/hardware/contexthub/HubEndpointDiscoveryCallback.java
index a61a7eb..4672bbb 100644
--- a/core/java/android/hardware/contexthub/IHubEndpointDiscoveryCallback.java
+++ b/core/java/android/hardware/contexthub/HubEndpointDiscoveryCallback.java
@@ -30,7 +30,7 @@
  */
 @SystemApi
 @FlaggedApi(Flags.FLAG_OFFLOAD_API)
-public interface IHubEndpointDiscoveryCallback {
+public interface HubEndpointDiscoveryCallback {
     /**
      * Called when a list of hub endpoints have started.
      *
diff --git a/core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java b/core/java/android/hardware/contexthub/HubEndpointLifecycleCallback.java
similarity index 97%
rename from core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java
rename to core/java/android/hardware/contexthub/HubEndpointLifecycleCallback.java
index 698ed0a..6d75010 100644
--- a/core/java/android/hardware/contexthub/IHubEndpointLifecycleCallback.java
+++ b/core/java/android/hardware/contexthub/HubEndpointLifecycleCallback.java
@@ -29,7 +29,7 @@
  */
 @SystemApi
 @FlaggedApi(Flags.FLAG_OFFLOAD_API)
-public interface IHubEndpointLifecycleCallback {
+public interface HubEndpointLifecycleCallback {
     /**
      * Called when an endpoint is requesting a session be opened with another endpoint.
      *
diff --git a/core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java b/core/java/android/hardware/contexthub/HubEndpointMessageCallback.java
similarity index 89%
rename from core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java
rename to core/java/android/hardware/contexthub/HubEndpointMessageCallback.java
index fde7017..5db54ef 100644
--- a/core/java/android/hardware/contexthub/IHubEndpointMessageCallback.java
+++ b/core/java/android/hardware/contexthub/HubEndpointMessageCallback.java
@@ -26,18 +26,18 @@
  * <p>This interface can be attached to an endpoint through {@link
  * HubEndpoint.Builder#setMessageCallback} method. Methods in this interface will only be called
  * when the endpoint is currently registered and has an open session. The endpoint will receive
- * session lifecycle callbacks through {@link IHubEndpointLifecycleCallback}.
+ * session lifecycle callbacks through {@link HubEndpointLifecycleCallback}.
  *
  * @hide
  */
 @SystemApi
 @FlaggedApi(Flags.FLAG_OFFLOAD_API)
-public interface IHubEndpointMessageCallback {
+public interface HubEndpointMessageCallback {
     /**
      * Callback interface for receiving messages for a particular endpoint session.
      *
      * @param session The session this message is sent through. Previously specified in a {@link
-     *     IHubEndpointLifecycleCallback#onSessionOpened(HubEndpointSession)} call.
+     *     HubEndpointLifecycleCallback#onSessionOpened(HubEndpointSession)} call.
      * @param message The {@link HubMessage} object representing a message received by the endpoint
      *     that registered this callback interface. This message is constructed by the
      */
diff --git a/core/java/android/hardware/contexthub/HubEndpointSession.java b/core/java/android/hardware/contexthub/HubEndpointSession.java
index 77f937e..dd6e52f 100644
--- a/core/java/android/hardware/contexthub/HubEndpointSession.java
+++ b/core/java/android/hardware/contexthub/HubEndpointSession.java
@@ -79,7 +79,7 @@
             throw new IllegalStateException("Session is already closed.");
         }
 
-        boolean isResponseRequired = message.getDeliveryParams().isResponseRequired();
+        boolean isResponseRequired = message.isResponseRequired();
         ContextHubTransaction<Void> ret =
                 new ContextHubTransaction<>(
                         isResponseRequired
@@ -137,7 +137,7 @@
      * no service associated to this session.
      *
      * <p>For hub initiated sessions, the object was previously used in as an argument for open
-     * request in {@link IHubEndpointLifecycleCallback#onSessionOpenRequest}.
+     * request in {@link HubEndpointLifecycleCallback#onSessionOpenRequest}.
      *
      * <p>For app initiated sessions, the object was previously used in an open request in {@link
      * android.hardware.location.ContextHubManager#openSession}
diff --git a/core/java/android/hardware/contexthub/HubEndpointSessionResult.java b/core/java/android/hardware/contexthub/HubEndpointSessionResult.java
index 1f2bdb9..b193d00 100644
--- a/core/java/android/hardware/contexthub/HubEndpointSessionResult.java
+++ b/core/java/android/hardware/contexthub/HubEndpointSessionResult.java
@@ -23,7 +23,7 @@
 import android.chre.flags.Flags;
 
 /**
- * Return type of {@link IHubEndpointLifecycleCallback#onSessionOpenRequest}. The value determines
+ * Return type of {@link HubEndpointLifecycleCallback#onSessionOpenRequest}. The value determines
  * whether a open session request from the remote is accepted or not.
  *
  * @hide
diff --git a/core/java/android/hardware/contexthub/HubMessage.java b/core/java/android/hardware/contexthub/HubMessage.java
index dc8a8c5..8a8617d 100644
--- a/core/java/android/hardware/contexthub/HubMessage.java
+++ b/core/java/android/hardware/contexthub/HubMessage.java
@@ -29,7 +29,8 @@
 import java.util.Objects;
 
 /**
- * A class describing general messages send through the Context Hub Service.
+ * A class describing general messages send through the Context Hub Service through {@link
+ * HubEndpointSession#sendMessage}.
  *
  * @hide
  */
@@ -41,101 +42,14 @@
     private final int mMessageType;
     private final byte[] mMessageBody;
 
-    private final DeliveryParams mDeliveryParams;
+    private final boolean mResponseRequired;
     private int mMessageSequenceNumber;
 
-    /**
-     * Configurable options for message delivery. This option can be passed into {@link
-     * HubEndpointSession#sendMessage} to specify the behavior of message delivery.
-     */
-    public static class DeliveryParams {
-        private boolean mResponseRequired;
-
-        private DeliveryParams(boolean responseRequired) {
-            mResponseRequired = responseRequired;
-        }
-
-        /** Get the acknowledgement requirement. */
-        public boolean isResponseRequired() {
-            return mResponseRequired;
-        }
-
-        /**
-         * Set the response requirement for a message. Message sent with this option will have a
-         * {@link android.hardware.location.ContextHubTransaction.Response} when the peer received
-         * the message. Default is false.
-         */
-        @NonNull
-        public DeliveryParams setResponseRequired(boolean required) {
-            mResponseRequired = required;
-            return this;
-        }
-
-        /** Construct a default delivery option. */
-        @NonNull
-        public static DeliveryParams makeBasic() {
-            return new DeliveryParams(false);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder out = new StringBuilder();
-            out.append("DeliveryParams[");
-            out.append("responseRequired = ").append(mResponseRequired);
-            out.append("]");
-            return out.toString();
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mResponseRequired);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == this) {
-                return true;
-            }
-
-            if (obj instanceof DeliveryParams other) {
-                return other.mResponseRequired == mResponseRequired;
-            }
-
-            return false;
-        }
-    }
-
-    private HubMessage(int messageType, byte[] messageBody, DeliveryParams deliveryParams) {
+    private HubMessage(int messageType, @NonNull byte[] messageBody, boolean responseRequired) {
+        Objects.requireNonNull(messageBody, "messageBody cannot be null");
         mMessageType = messageType;
         mMessageBody = messageBody;
-        mDeliveryParams = deliveryParams;
-    }
-
-    /**
-     * Creates a HubMessage object to send to through an endpoint.
-     *
-     * @param messageType the endpoint & service dependent message type
-     * @param messageBody the byte array message contents
-     * @return the HubMessage object
-     */
-    @NonNull
-    public static HubMessage createMessage(int messageType, @NonNull byte[] messageBody) {
-        return new HubMessage(messageType, messageBody, DeliveryParams.makeBasic());
-    }
-
-    /**
-     * Creates a HubMessage object to send to through an endpoint.
-     *
-     * @param messageType the endpoint & service dependent message type
-     * @param messageBody the byte array message contents
-     * @param deliveryParams The message delivery parameters. See {@link HubMessage.DeliveryParams}
-     *     for more details.
-     * @return the HubMessage object
-     */
-    @NonNull
-    public static HubMessage createMessage(
-            int messageType, @NonNull byte[] messageBody, @NonNull DeliveryParams deliveryParams) {
-        return new HubMessage(messageType, messageBody, deliveryParams);
+        mResponseRequired = responseRequired;
     }
 
     /**
@@ -158,12 +72,10 @@
     }
 
     /**
-     * Retrieve the {@link DeliveryParams} object specifying the behavior of message delivery.
-     *
-     * @hide
+     * @return true if a response is required when the peer endpoint receives the message.
      */
-    public DeliveryParams getDeliveryParams() {
-        return mDeliveryParams;
+    public boolean isResponseRequired() {
+        return mResponseRequired;
     }
 
     /**
@@ -192,8 +104,7 @@
         mMessageBody = new byte[msgSize];
         in.readByteArray(mMessageBody);
 
-        mDeliveryParams = DeliveryParams.makeBasic();
-        mDeliveryParams.setResponseRequired(in.readInt() == 1);
+        mResponseRequired = (in.readInt() == 1);
         mMessageSequenceNumber = in.readInt();
     }
 
@@ -209,7 +120,7 @@
         out.writeInt(mMessageBody.length);
         out.writeByteArray(mMessageBody);
 
-        out.writeInt(mDeliveryParams.isResponseRequired() ? 1 : 0);
+        out.writeInt(mResponseRequired ? 1 : 0);
         out.writeInt(mMessageSequenceNumber);
     }
 
@@ -235,7 +146,7 @@
         out.append("HubMessage[type = ").append(mMessageType);
         out.append(", length = ").append(mMessageBody.length);
         out.append(", messageSequenceNumber = ").append(mMessageSequenceNumber);
-        out.append(", deliveryParams = ").append(mDeliveryParams);
+        out.append(", responseRequired = ").append(mResponseRequired);
         out.append("](");
 
         if (length > 0) {
@@ -267,7 +178,7 @@
             isEqual =
                     (other.getMessageType() == mMessageType)
                             && Arrays.equals(other.getMessageBody(), mMessageBody)
-                            && (other.getDeliveryParams().equals(mDeliveryParams))
+                            && (other.isResponseRequired() == mResponseRequired)
                             && (other.getMessageSequenceNumber() == mMessageSequenceNumber);
         }
 
@@ -283,7 +194,41 @@
         return Objects.hash(
                 mMessageType,
                 Arrays.hashCode(mMessageBody),
-                mDeliveryParams,
+                mResponseRequired,
                 mMessageSequenceNumber);
     }
+
+    public static final class Builder {
+        private int mMessageType;
+        private byte[] mMessageBody;
+        private boolean mResponseRequired = false;
+
+        /**
+         * Create a builder for {@link HubMessage} with a default delivery parameters.
+         *
+         * @param messageType the endpoint & service dependent message type
+         * @param messageBody the byte array message contents
+         */
+        public Builder(int messageType, @NonNull byte[] messageBody) {
+            mMessageType = messageType;
+            mMessageBody = messageBody;
+        }
+
+        /**
+         * @param responseRequired If true, message sent with this option will have a {@link
+         *     android.hardware.location.ContextHubTransaction.Response} when the peer received the
+         *     message. Default is false.
+         */
+        @NonNull
+        public Builder setResponseRequired(boolean responseRequired) {
+            mResponseRequired = responseRequired;
+            return this;
+        }
+
+        /** Build the {@link HubMessage} object. */
+        @NonNull
+        public HubMessage build() {
+            return new HubMessage(mMessageType, mMessageBody, mResponseRequired);
+        }
+    }
 }
diff --git a/core/java/android/hardware/contexthub/HubServiceInfo.java b/core/java/android/hardware/contexthub/HubServiceInfo.java
index 2f33e8f..651be3b 100644
--- a/core/java/android/hardware/contexthub/HubServiceInfo.java
+++ b/core/java/android/hardware/contexthub/HubServiceInfo.java
@@ -112,6 +112,7 @@
      * <p>The value can be one of {@link HubServiceInfo#FORMAT_CUSTOM}, {@link
      * HubServiceInfo#FORMAT_AIDL} or {@link HubServiceInfo#FORMAT_PW_RPC_PROTOBUF}.
      */
+    @ServiceFormat
     public int getFormat() {
         return mFormat;
     }
@@ -178,7 +179,8 @@
          *   <li>Pigweed RPC with Protobuf: com.example.proto.ExampleService
          * </ol>
          *
-         * @param serviceDescriptor The service descriptor.
+         * @param serviceDescriptor The service descriptor for the interface, provided by the
+         *     vendor.
          * @param format One of {@link HubServiceInfo#FORMAT_CUSTOM}, {@link
          *     HubServiceInfo#FORMAT_AIDL} or {@link HubServiceInfo#FORMAT_PW_RPC_PROTOBUF}.
          * @param majorVersion Breaking changes should be a major version bump.
diff --git a/core/java/android/hardware/devicestate/DeviceState.java b/core/java/android/hardware/devicestate/DeviceState.java
index 8b4d0da..d03795d 100644
--- a/core/java/android/hardware/devicestate/DeviceState.java
+++ b/core/java/android/hardware/devicestate/DeviceState.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.hardware.devicestate.feature.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
@@ -49,7 +50,7 @@
  * @see DeviceStateManager
  */
 @SystemApi
-@FlaggedApi(android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_PROPERTY_API)
+@FlaggedApi(Flags.FLAG_DEVICE_STATE_PROPERTY_API)
 public final class DeviceState {
     /**
      * Property that indicates that a fold-in style foldable device is currently in a fully closed
@@ -178,15 +179,12 @@
      * is the default display where the app is shown, and the inner display is used by the system to
      * show a UI affordance for exiting the mode.
      *
-     * Note that this value should generally not be used, and may be removed in the future (e.g.
-     * if or when it becomes the only type of rear display mode when
-     * {@link android.hardware.devicestate.feature.flags.Flags#deviceStateRdmV2} is removed).
-     *
-     * As such, clients should strongly consider relying on {@link #PROPERTY_FEATURE_REAR_DISPLAY}
-     * instead.
+     * Clients should strongly consider relying on {@link #PROPERTY_FEATURE_REAR_DISPLAY} instead.
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(Flags.FLAG_DEVICE_STATE_RDM_V2)
     public static final int PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT = 1001;
 
     /** @hide */
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 7054c37..6716598 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -578,73 +578,82 @@
     /**
      * @hide
      */
-    @LongDef(flag = true, prefix = {"EVENT_FLAG_"}, value = {
-            EVENT_FLAG_DISPLAY_ADDED,
-            EVENT_FLAG_DISPLAY_CHANGED,
-            EVENT_FLAG_DISPLAY_REMOVED,
-            EVENT_FLAG_DISPLAY_REFRESH_RATE,
-            EVENT_FLAG_DISPLAY_STATE
+    @LongDef(flag = true, prefix = {"EVENT_TYPE_"}, value = {
+            EVENT_TYPE_DISPLAY_ADDED,
+            EVENT_TYPE_DISPLAY_CHANGED,
+            EVENT_TYPE_DISPLAY_REMOVED,
+            EVENT_TYPE_DISPLAY_REFRESH_RATE,
+            EVENT_TYPE_DISPLAY_STATE
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface EventFlag {}
+    public @interface EventType {}
 
     /**
      * @hide
      */
-    @LongDef(flag = true, prefix = {"PRIVATE_EVENT_FLAG_"}, value = {
-            PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
-            PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED,
-            PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+    @LongDef(flag = true, prefix = {"PRIVATE_EVENT_TYPE_"}, value = {
+            PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS,
+            PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED,
+            PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED,
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface PrivateEventFlag {}
+    public @interface PrivateEventType {}
 
     /**
-     * Event type for when a new display is added.
+     * Event type for when a new display is added. This notification is sent
+     * through the {@link DisplayListener#onDisplayAdded} callback method
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      *
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
+    public static final long EVENT_TYPE_DISPLAY_ADDED = 1L << 0;
 
     /**
-     * Event type for when a display is removed.
+     * Event type for when a display is removed. This notification is sent
+     * through the {@link DisplayListener#onDisplayRemoved} callback method
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      *
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1;
+    public static final long EVENT_TYPE_DISPLAY_REMOVED = 1L << 1;
 
     /**
-     * Event type for when a display is changed.
+     * Event type for when a display is changed. {@link DisplayListener#onDisplayChanged} callback
+     * is triggered whenever the properties of a {@link android.view.Display}, such as size,
+     * state, density are modified.
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      *
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2;
-
+    public static final long EVENT_TYPE_DISPLAY_CHANGED = 1L << 2;
 
     /**
-     * Event flag to register for a display's refresh rate changes.
+     * Event type for when a display's refresh rate changes.
+     * {@link DisplayListener#onDisplayChanged} callback is triggered whenever the refresh rate
+     * of the display changes. New refresh rate values can be retrieved via
+     * {@link Display#getRefreshRate()}.
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public static final long EVENT_FLAG_DISPLAY_REFRESH_RATE = 1L << 3;
+    public static final long EVENT_TYPE_DISPLAY_REFRESH_RATE = 1L << 3;
 
     /**
-     * Event flag to register for a display state changes.
+     * Event type for when a display state changes.
+     * {@link DisplayListener#onDisplayChanged} callback is triggered whenever the state
+     * of the display changes. New state values can be retrieved via
+     * {@link Display#getState()}.
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public static final long EVENT_FLAG_DISPLAY_STATE = 1L << 4;
+    public static final long EVENT_TYPE_DISPLAY_STATE = 1L << 4;
 
     /**
-     * Event flag to register for a display's brightness changes. This notification is sent
+     * Event type to register for a display's brightness changes. This notification is sent
      * through the {@link DisplayListener#onDisplayChanged} callback method. New brightness
      * values can be retrieved via {@link android.view.Display#getBrightnessInfo()}.
      *
@@ -652,10 +661,10 @@
      *
      * @hide
      */
-    public static final long PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS = 1L << 0;
+    public static final long PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS = 1L << 0;
 
     /**
-     * Event flag to register for a display's hdr/sdr ratio changes. This notification is sent
+     * Event type to register for a display's hdr/sdr ratio changes. This notification is sent
      * through the {@link DisplayListener#onDisplayChanged} callback method. New hdr/sdr
      * values can be retrieved via {@link Display#getHdrSdrRatio()}.
      *
@@ -665,15 +674,15 @@
      *
      * @hide
      */
-    public static final long PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED = 1L << 1;
+    public static final long PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED = 1L << 1;
 
     /**
-     * Event flag to register for a display's connection changed.
+     * Event type to register for a display's connection changed.
      *
      * @see #registerDisplayListener(DisplayListener, Handler, long)
      * @hide
      */
-    public static final long PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED = 1L << 2;
+    public static final long PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED = 1L << 2;
 
 
     /** @hide */
@@ -800,8 +809,8 @@
      * @see #unregisterDisplayListener
      */
     public void registerDisplayListener(DisplayListener listener, Handler handler) {
-        registerDisplayListener(listener, handler, EVENT_FLAG_DISPLAY_ADDED
-                | EVENT_FLAG_DISPLAY_CHANGED | EVENT_FLAG_DISPLAY_REMOVED);
+        registerDisplayListener(listener, handler, EVENT_TYPE_DISPLAY_ADDED
+                | EVENT_TYPE_DISPLAY_CHANGED | EVENT_TYPE_DISPLAY_REMOVED);
     }
 
     /**
@@ -810,7 +819,7 @@
      * @param listener The listener to register.
      * @param handler The handler on which the listener should be invoked, or null
      * if the listener should be invoked on the calling thread's looper.
-     * @param eventFlags A bitmask of the event types for which this listener is subscribed.
+     * @param eventFilter A bitmask of the event types for which this listener is subscribed.
      *
      * @see #registerDisplayListener(DisplayListener, Handler)
      * @see #unregisterDisplayListener
@@ -818,9 +827,9 @@
      * @hide
      */
     public void registerDisplayListener(@NonNull DisplayListener listener,
-            @Nullable Handler handler, @EventFlag long eventFlags) {
+            @Nullable Handler handler, @EventType long eventFilter) {
         mGlobal.registerDisplayListener(listener, handler,
-                mGlobal.mapFlagsToInternalEventFlag(eventFlags, 0),
+                mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
                 ActivityThread.currentPackageName());
     }
 
@@ -829,17 +838,17 @@
      *
      * @param listener The listener to register.
      * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null.
-     * @param eventFlags A bitmask of the event types for which this listener is subscribed.
+     * @param eventFilter A bitmask of the event types for which this listener is subscribed.
      *
      * @see #registerDisplayListener(DisplayListener, Handler)
      * @see #unregisterDisplayListener
      *
      */
     @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public void registerDisplayListener(@NonNull Executor executor, @EventFlag long eventFlags,
+    public void registerDisplayListener(@NonNull Executor executor, @EventType long eventFilter,
             @NonNull DisplayListener listener) {
         mGlobal.registerDisplayListener(listener, executor,
-                mGlobal.mapFlagsToInternalEventFlag(eventFlags, 0),
+                mGlobal.mapFiltersToInternalEventFlag(eventFilter, 0),
                 ActivityThread.currentPackageName());
     }
 
@@ -849,8 +858,8 @@
      * @param listener The listener to register.
      * @param handler The handler on which the listener should be invoked, or null
      * if the listener should be invoked on the calling thread's looper.
-     * @param eventFlags A bitmask of the event types for which this listener is subscribed.
-     * @param privateEventFlags A bitmask of the private event types for which this listener
+     * @param eventFilter A bitmask of the event types for which this listener is subscribed.
+     * @param privateEventFilter A bitmask of the private event types for which this listener
      *                          is subscribed.
      *
      * @see #registerDisplayListener(DisplayListener, Handler)
@@ -859,10 +868,10 @@
      * @hide
      */
     public void registerDisplayListener(@NonNull DisplayListener listener,
-            @Nullable Handler handler, @EventFlag long eventFlags,
-            @PrivateEventFlag long privateEventFlags) {
+            @Nullable Handler handler, @EventType long eventFilter,
+            @PrivateEventType long privateEventFilter) {
         mGlobal.registerDisplayListener(listener, handler,
-                mGlobal.mapFlagsToInternalEventFlag(eventFlags, privateEventFlags),
+                mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter),
                 ActivityThread.currentPackageName());
     }
 
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index ffa5460..b5715ed 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -18,7 +18,7 @@
 
 
 import static android.app.PropertyInvalidatedCache.MODULE_SYSTEM;
-import static android.hardware.display.DisplayManager.EventFlag;
+import static android.hardware.display.DisplayManager.EventType;
 import static android.Manifest.permission.MANAGE_DISPLAYS;
 import static android.view.Display.HdrCapabilities.HdrType;
 
@@ -106,7 +106,7 @@
 
     @IntDef(prefix = {"EVENT_DISPLAY_"}, flag = true, value = {
             EVENT_DISPLAY_ADDED,
-            EVENT_DISPLAY_CHANGED,
+            EVENT_DISPLAY_BASIC_CHANGED,
             EVENT_DISPLAY_REMOVED,
             EVENT_DISPLAY_BRIGHTNESS_CHANGED,
             EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED,
@@ -119,7 +119,8 @@
     public @interface DisplayEvent {}
 
     public static final int EVENT_DISPLAY_ADDED = 1;
-    public static final int EVENT_DISPLAY_CHANGED = 2;
+    public static final int EVENT_DISPLAY_BASIC_CHANGED = 2;
+
     public static final int EVENT_DISPLAY_REMOVED = 3;
     public static final int EVENT_DISPLAY_BRIGHTNESS_CHANGED = 4;
     public static final int EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED = 5;
@@ -130,7 +131,7 @@
 
     @LongDef(prefix = {"INTERNAL_EVENT_FLAG_"}, flag = true, value = {
             INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
-            INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+            INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED,
             INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
             INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
             INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
@@ -143,7 +144,7 @@
     public @interface InternalEventFlag {}
 
     public static final long INTERNAL_EVENT_FLAG_DISPLAY_ADDED = 1L << 0;
-    public static final long INTERNAL_EVENT_FLAG_DISPLAY_CHANGED = 1L << 1;
+    public static final long INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED = 1L << 1;
     public static final long INTERNAL_EVENT_FLAG_DISPLAY_REMOVED = 1L << 2;
     public static final long INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED = 1L << 3;
     public static final long INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED = 1L << 4;
@@ -485,7 +486,7 @@
         // There can be racing condition between DMS and WMS callbacks, so force triggering the
         // listener to make sure the client can get the onDisplayChanged callback even if
         // DisplayInfo is not changed (Display read from both DisplayInfo and WindowConfiguration).
-        handleDisplayEvent(displayId, EVENT_DISPLAY_CHANGED, true /* forceUpdate */);
+        handleDisplayEvent(displayId, EVENT_DISPLAY_BASIC_CHANGED, true /* forceUpdate */);
     }
 
     private static Looper getLooperForHandler(@Nullable Handler handler) {
@@ -518,7 +519,8 @@
         }
         if (mDispatchNativeCallbacks) {
             mask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-                    | INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+                    | INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                    | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
                     | INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
         }
         if (!mTopologyListeners.isEmpty()) {
@@ -571,7 +573,8 @@
             }
 
             info = getDisplayInfoLocked(displayId);
-            if (event == EVENT_DISPLAY_CHANGED && mDispatchNativeCallbacks) {
+            if ((event == EVENT_DISPLAY_BASIC_CHANGED
+                    || event == EVENT_DISPLAY_REFRESH_RATE_CHANGED) && mDispatchNativeCallbacks) {
                 // Choreographer only supports a single display, so only dispatch refresh rate
                 // changes for the default display.
                 if (displayId == Display.DEFAULT_DISPLAY) {
@@ -1492,9 +1495,9 @@
                         mListener.onDisplayAdded(displayId);
                     }
                     break;
-                case EVENT_DISPLAY_CHANGED:
-                    if ((mInternalEventFlagsMask & INTERNAL_EVENT_FLAG_DISPLAY_CHANGED)
-                            != 0) {
+                case EVENT_DISPLAY_BASIC_CHANGED:
+                    if ((mInternalEventFlagsMask
+                            & INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED) != 0) {
                         if (info != null && (forceUpdate || !info.equals(mDisplayInfo))) {
                             if (extraLogging()) {
                                 Slog.i(TAG, "Sending onDisplayChanged: Display Changed. Info: "
@@ -1691,8 +1694,8 @@
         switch (event) {
             case EVENT_DISPLAY_ADDED:
                 return "ADDED";
-            case EVENT_DISPLAY_CHANGED:
-                return "CHANGED";
+            case EVENT_DISPLAY_BASIC_CHANGED:
+                return "BASIC_CHANGED";
             case EVENT_DISPLAY_REMOVED:
                 return "REMOVED";
             case EVENT_DISPLAY_BRIGHTNESS_CHANGED:
@@ -1734,49 +1737,53 @@
      * @return returns the bitmask of both public and private event flags unified to
      * InternalEventFlag
      */
-    public @InternalEventFlag long mapFlagsToInternalEventFlag(@EventFlag long eventFlags,
-            @DisplayManager.PrivateEventFlag long privateEventFlags) {
+    public @InternalEventFlag long mapFiltersToInternalEventFlag(@EventType long eventFlags,
+            @DisplayManager.PrivateEventType long privateEventFlags) {
         return mapPrivateEventFlags(privateEventFlags) | mapPublicEventFlags(eventFlags);
     }
 
-    private long mapPrivateEventFlags(@DisplayManager.PrivateEventFlag long privateEventFlags) {
+    private long mapPrivateEventFlags(@DisplayManager.PrivateEventType long privateEventFlags) {
         long baseEventMask = 0;
-        if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0) {
+        if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS) != 0) {
             baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED;
         }
 
-        if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0) {
+        if ((privateEventFlags & DisplayManager.PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED) != 0) {
             baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED;
         }
 
         if ((privateEventFlags
-                & DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) {
+                & DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED) != 0) {
             baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED;
         }
         return baseEventMask;
     }
 
-    private long mapPublicEventFlags(@EventFlag long eventFlags) {
+    private long mapPublicEventFlags(@EventType long eventFlags) {
         long baseEventMask = 0;
-        if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0) {
+        if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_ADDED) != 0) {
             baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_ADDED;
         }
 
-        if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0) {
-            baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_CHANGED;
+        if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_CHANGED) != 0) {
+            // For backward compatibility, a client subscribing to
+            // DisplayManager.EVENT_FLAG_DISPLAY_CHANGED will be enrolled to both Basic and
+            // RR changes
+            baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                    | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
         }
 
         if ((eventFlags
-                & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0) {
+                & DisplayManager.EVENT_TYPE_DISPLAY_REMOVED) != 0) {
             baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
         }
 
         if (Flags.displayListenerPerformanceImprovements()) {
-            if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE) != 0) {
+            if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_REFRESH_RATE) != 0) {
                 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
             }
 
-            if ((eventFlags & DisplayManager.EVENT_FLAG_DISPLAY_STATE) != 0) {
+            if ((eventFlags & DisplayManager.EVENT_TYPE_DISPLAY_STATE) != 0) {
                 baseEventMask |= INTERNAL_EVENT_FLAG_DISPLAY_STATE;
             }
         }
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 68b6cfc..d273ddb 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -449,6 +449,11 @@
     public abstract IntArray getDisplayIds();
 
     /**
+     * Get group id for given display id
+     */
+    public abstract int getGroupIdForDisplay(int displayId);
+
+    /**
      * Called upon presentation started/ended on the display.
      * @param displayId the id of the display where presentation started.
      * @param isShown whether presentation is shown.
diff --git a/core/java/android/hardware/display/DisplayTopology.java b/core/java/android/hardware/display/DisplayTopology.java
index 211aeff..ba5dfc0 100644
--- a/core/java/android/hardware/display/DisplayTopology.java
+++ b/core/java/android/hardware/display/DisplayTopology.java
@@ -129,14 +129,38 @@
     }
 
     /**
+     * Update the size of a display and normalize the topology.
+     * @param displayId The logical display ID
+     * @param width The new width
+     * @param height The new height
+     * @return True if the topology has changed.
+     */
+    public boolean updateDisplay(int displayId, float width, float height) {
+        TreeNode display = findDisplay(displayId, mRoot);
+        if (display == null) {
+            return false;
+        }
+        if (floatEquals(display.mWidth, width) && floatEquals(display.mHeight, height)) {
+            return false;
+        }
+        display.mWidth = width;
+        display.mHeight = height;
+        normalize();
+        Slog.i(TAG, "Display with ID " + displayId + " updated, new width: " + width
+                + ", new height: " + height);
+        return true;
+    }
+
+    /**
      * Remove a display from the topology.
      * The default topology is created from the remaining displays, as if they were reconnected
      * one by one.
      * @param displayId The logical display ID
+     * @return True if the display was present in the topology and removed.
      */
-    public void removeDisplay(int displayId) {
+    public boolean removeDisplay(int displayId) {
         if (findDisplay(displayId, mRoot) == null) {
-            return;
+            return false;
         }
         Queue<TreeNode> queue = new ArrayDeque<>();
         queue.add(mRoot);
@@ -159,6 +183,7 @@
         } else {
             Slog.i(TAG, "Display with ID " + displayId + " removed");
         }
+        return true;
     }
 
     /**
@@ -685,12 +710,12 @@
         /**
          * The width of the display in density-independent pixels (dp).
          */
-        private final float mWidth;
+        private float mWidth;
 
         /**
          * The height of the display in density-independent pixels (dp).
          */
-        private final float mHeight;
+        private float mHeight;
 
         /**
          * The position of this display relative to its parent.
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 4fbdf7f..d88a9d4 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -56,15 +56,18 @@
     void stopWifiDisplayScan();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void connectWifiDisplay(String address);
 
     // No permissions required.
     void disconnectWifiDisplay();
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void renameWifiDisplay(String address, String alias);
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
+    @EnforcePermission("CONFIGURE_WIFI_DISPLAY")
     void forgetWifiDisplay(String address);
 
     // Requires CONFIGURE_WIFI_DISPLAY permission.
@@ -169,6 +172,7 @@
     void setBrightness(int displayId, float brightness);
 
     // Retrieves the display brightness.
+    @EnforcePermission("CONTROL_DISPLAY_BRIGHTNESS")
     float getBrightness(int displayId);
 
     // Temporarily sets the auto brightness adjustment factor.
@@ -196,8 +200,7 @@
 
     // Sets the HDR conversion mode for a device.
     // Requires MODIFY_HDR_CONVERSION_MODE permission.
-    @JavaPassthrough(annotation = "@android.annotation.RequiresPermission(android.Manifest"
-                + ".permission.MODIFY_HDR_CONVERSION_MODE)")
+    @EnforcePermission("MODIFY_HDR_CONVERSION_MODE")
     void setHdrConversionMode(in HdrConversionMode hdrConversionMode);
     HdrConversionMode getHdrConversionModeSetting();
     HdrConversionMode getHdrConversionMode();
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 5c11346..3ef90e4 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -63,6 +63,7 @@
 import com.android.internal.os.SomeArgs;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Executor;
@@ -76,8 +77,9 @@
 public final class InputManagerGlobal {
     private static final String TAG = "InputManagerGlobal";
     // To enable these logs, run: 'adb shell setprop log.tag.InputManagerGlobal DEBUG'
-    // (requires restart)
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private boolean debug() {
+        return Log.isLoggable(TAG, Log.DEBUG);
+    }
 
     @GuardedBy("mInputDeviceListeners")
     @Nullable private SparseArray<InputDevice> mInputDevices;
@@ -269,16 +271,19 @@
     }
 
     private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
-        if (DEBUG) {
-            Log.d(TAG, "Received input devices changed.");
+        final boolean enableDebugLogs = debug();
+        if (enableDebugLogs) {
+            Log.d(TAG, "Received input devices changed: " + Arrays.toString(deviceIdAndGeneration));
         }
 
         synchronized (mInputDeviceListeners) {
             for (int i = mInputDevices.size(); --i > 0; ) {
                 final int deviceId = mInputDevices.keyAt(i);
                 if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Device removed: " + deviceId);
+                    if (enableDebugLogs) {
+                        final InputDevice device = mInputDevices.valueAt(i);
+                        final String name = device != null ? device.getName() : "<null>";
+                        Log.d(TAG, "Device removed: " + deviceId + " (" + name + ")");
                     }
                     mInputDevices.removeAt(i);
                     if (mInputDeviceSensorManager != null) {
@@ -297,8 +302,9 @@
                     if (device != null) {
                         final int generation = deviceIdAndGeneration[i + 1];
                         if (device.getGeneration() != generation) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Device changed: " + deviceId);
+                            if (enableDebugLogs) {
+                                Log.d(TAG, "Device changed: " + deviceId + " ("
+                                        + device.getName() + ")");
                             }
                             mInputDevices.setValueAt(index, null);
                             if (mInputDeviceSensorManager != null) {
@@ -309,7 +315,7 @@
                         }
                     }
                 } else {
-                    if (DEBUG) {
+                    if (enableDebugLogs) {
                         Log.d(TAG, "Device added: " + deviceId);
                     }
                     mInputDevices.put(deviceId, null);
@@ -517,7 +523,7 @@
     }
 
     private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
-        if (DEBUG) {
+        if (debug()) {
             Log.d(TAG, "Received tablet mode changed: "
                     + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
         }
diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java
index f8f7f5e..34c88e9 100644
--- a/core/java/android/hardware/input/InputSettings.java
+++ b/core/java/android/hardware/input/InputSettings.java
@@ -25,6 +25,7 @@
 import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
 import static com.android.hardware.input.Flags.keyboardA11ySlowKeysFlag;
 import static com.android.hardware.input.Flags.keyboardA11yStickyKeysFlag;
+import static com.android.hardware.input.Flags.mouseScrollingAcceleration;
 import static com.android.hardware.input.Flags.mouseReverseVerticalScrolling;
 import static com.android.hardware.input.Flags.mouseSwapPrimaryButton;
 import static com.android.hardware.input.Flags.touchpadSystemGestureDisable;
@@ -392,6 +393,15 @@
     }
 
     /**
+     * Returns true if the feature flag for toggling the mouse scrolling acceleration is enabled.
+     *
+     * @hide
+     */
+    public static boolean isMouseScrollingAccelerationFeatureFlagEnabled() {
+        return mouseScrollingAcceleration();
+    }
+
+    /**
      * Returns true if the feature flag for mouse reverse vertical scrolling is enabled.
      * @hide
      */
@@ -593,7 +603,44 @@
     }
 
     /**
-     * Whether mouse vertical scrolling is enabled, this applies only to connected mice.
+     * Whether mouse scrolling acceleration is enabled. This applies only to connected mice.
+     *
+     * @param context The application context.
+     * @return Whether the mouse scrolling is accelerated based on the user's scrolling speed.
+     *
+     * @hide
+     */
+    public static boolean isMouseScrollingAccelerationEnabled(@NonNull Context context) {
+        if (!isMouseScrollingAccelerationFeatureFlagEnabled()) {
+            return true;
+        }
+
+        return Settings.System.getIntForUser(context.getContentResolver(),
+            Settings.System.MOUSE_SCROLLING_ACCELERATION, 0, UserHandle.USER_CURRENT) != 0;
+    }
+
+    /**
+     * Sets whether the connected mouse scrolling acceleration is enabled.
+     *
+     * @param context The application context.
+     * @param scrollingAcceleration Whether mouse scrolling acceleration is enabled.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
+    public static void setMouseScrollingAcceleration(@NonNull Context context,
+            boolean scrollingAcceleration) {
+        if (!isMouseScrollingAccelerationFeatureFlagEnabled()) {
+            return;
+        }
+
+        Settings.System.putIntForUser(context.getContentResolver(),
+                Settings.System.MOUSE_SCROLLING_ACCELERATION, scrollingAcceleration ? 1 : 0,
+                UserHandle.USER_CURRENT);
+    }
+
+    /**
+     * Whether mouse vertical scrolling is reversed. This applies only to connected mice.
      *
      * @param context The application context.
      * @return Whether the mouse will have its vertical scrolling reversed
diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java
index 9f8505f..66d073f 100644
--- a/core/java/android/hardware/input/KeyGestureEvent.java
+++ b/core/java/android/hardware/input/KeyGestureEvent.java
@@ -119,16 +119,16 @@
     public static final int KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW = 69;
     public static final int KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW = 70;
     public static final int KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW = 71;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN = 72;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT = 73;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN = 72;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT = 73;
     public static final int KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION = 74;
     public static final int KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK = 75;
     public static final int KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW = 76;
     public static final int KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB = 77;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT = 78;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT = 79;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP = 80;
-    public static final int KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN = 81;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT = 78;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT = 79;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP = 80;
+    public static final int KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN = 81;
 
     public static final int FLAG_CANCELLED = 1;
 
@@ -215,16 +215,16 @@
             KEY_GESTURE_TYPE_SNAP_RIGHT_FREEFORM_WINDOW,
             KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW,
             KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW,
-            KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN,
-            KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT,
+            KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN,
+            KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT,
             KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION,
             KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK,
             KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW,
             KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB,
-            KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT,
-            KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT,
-            KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP,
-            KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN,
+            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT,
+            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT,
+            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP,
+            KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface KeyGestureType {
@@ -787,10 +787,10 @@
                 return "KEY_GESTURE_TYPE_MINIMIZE_FREEFORM_WINDOW";
             case KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW:
                 return "KEY_GESTURE_TYPE_TOGGLE_MAXIMIZE_FREEFORM_WINDOW";
-            case KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN";
-            case KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT";
             case KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION:
                 return "KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION";
             case KEY_GESTURE_TYPE_ACTIVATE_SELECT_TO_SPEAK:
@@ -799,14 +799,14 @@
                 return "KEY_GESTURE_TYPE_MAXIMIZE_FREEFORM_WINDOW";
             case KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB:
                 return "KEY_GESTURE_TYPE_TOGGLE_DO_NOT_DISTURB";
-            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT";
-            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT";
-            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP";
-            case KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN:
-                return "KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP";
+            case KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN:
+                return "KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN";
             default:
                 return Integer.toHexString(value);
         }
diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig
index 313bad5..c4d11cd 100644
--- a/core/java/android/hardware/input/input_framework.aconfig
+++ b/core/java/android/hardware/input/input_framework.aconfig
@@ -204,3 +204,10 @@
     description: "Allows the user to disable input scrolling acceleration for mouse."
     bug: "383555305"
 }
+
+flag {
+  name: "remove_fallback_modifiers"
+  namespace: "input"
+  description: "Removes modifiers from the original key event that activated the fallback, ensuring that only the intended fallback event is sent."
+  bug: "382545048"
+}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 1e0cc94..0cd3209 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -36,11 +36,11 @@
 import android.hardware.contexthub.ErrorCode;
 import android.hardware.contexthub.HubDiscoveryInfo;
 import android.hardware.contexthub.HubEndpoint;
+import android.hardware.contexthub.HubEndpointDiscoveryCallback;
 import android.hardware.contexthub.HubEndpointInfo;
+import android.hardware.contexthub.HubEndpointLifecycleCallback;
 import android.hardware.contexthub.HubServiceInfo;
 import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback;
-import android.hardware.contexthub.IHubEndpointDiscoveryCallback;
-import android.hardware.contexthub.IHubEndpointLifecycleCallback;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.Looper;
@@ -207,7 +207,7 @@
     private Handler mCallbackHandler;
 
     /** A map of endpoint discovery callbacks currently registered */
-    private Map<IHubEndpointDiscoveryCallback, IContextHubEndpointDiscoveryCallback>
+    private Map<HubEndpointDiscoveryCallback, IContextHubEndpointDiscoveryCallback>
             mDiscoveryCallbacks = new ConcurrentHashMap<>();
 
     /**
@@ -718,7 +718,19 @@
     /**
      * Find a list of endpoints that provides a specific service.
      *
-     * @param serviceDescriptor Statically generated ID for an endpoint.
+     * <p>Service descriptor should uniquely identify the interface (scoped to type). Convention of
+     * the descriptor depend on interface type.
+     *
+     * <p>Examples:
+     *
+     * <ol>
+     *   <li>AOSP-defined AIDL: android.hardware.something.IFoo/default
+     *   <li>Vendor-defined AIDL: com.example.something.IBar/default
+     *   <li>Pigweed RPC with Protobuf: com.example.proto.ExampleService
+     * </ol>
+     *
+     * @param serviceDescriptor The service descriptor for a service provided by the hub. The value
+     *     cannot be null or empty.
      * @return A list of {@link HubDiscoveryInfo} objects that represents the result of discovery.
      * @throws IllegalArgumentException if the serviceDescriptor is empty/null.
      */
@@ -750,14 +762,15 @@
     /**
      * Creates an interface to invoke endpoint discovery callbacks to send down to the service.
      *
-     * @param callback the callback to invoke at the client process
      * @param executor the executor to invoke callbacks for this client
+     * @param callback the callback to invoke at the client process
+     * @param serviceDescriptor an optional descriptor to match discovery list with
      * @return the callback interface
      */
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     private IContextHubEndpointDiscoveryCallback createDiscoveryCallback(
-            IHubEndpointDiscoveryCallback callback,
             Executor executor,
+            HubEndpointDiscoveryCallback callback,
             @Nullable String serviceDescriptor) {
         return new IContextHubEndpointDiscoveryCallback.Stub() {
             @Override
@@ -829,36 +842,36 @@
     }
 
     /**
-     * Equivalent to {@link #registerEndpointDiscoveryCallback(long, IHubEndpointDiscoveryCallback,
-     * Executor)} with the default executor in the main thread.
+     * Equivalent to {@link #registerEndpointDiscoveryCallback(Executor,
+     * HubEndpointDiscoveryCallback, long)} with the default executor in the main thread.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     public void registerEndpointDiscoveryCallback(
-            long endpointId, @NonNull IHubEndpointDiscoveryCallback callback) {
+            @NonNull HubEndpointDiscoveryCallback callback, long endpointId) {
         registerEndpointDiscoveryCallback(
-                endpointId, callback, new HandlerExecutor(Handler.getMain()));
+                new HandlerExecutor(Handler.getMain()), callback, endpointId);
     }
 
     /**
      * Registers a callback to be notified when the hub endpoint with the corresponding endpoint ID
      * has started or stopped.
      *
-     * @param endpointId The identifier of the hub endpoint.
-     * @param callback The callback to be invoked.
      * @param executor The executor to invoke the callback on.
+     * @param callback The callback to be invoked.
+     * @param endpointId The identifier of the hub endpoint.
      * @throws UnsupportedOperationException If the operation is not supported.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     public void registerEndpointDiscoveryCallback(
-            long endpointId,
-            @NonNull IHubEndpointDiscoveryCallback callback,
-            @NonNull Executor executor) {
-        Objects.requireNonNull(callback, "callback cannot be null");
+            @NonNull Executor executor,
+            @NonNull HubEndpointDiscoveryCallback callback,
+            long endpointId) {
         Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
         IContextHubEndpointDiscoveryCallback iCallback =
-                createDiscoveryCallback(callback, executor, null);
+                createDiscoveryCallback(executor, callback, null);
         try {
             mService.registerEndpointDiscoveryCallbackId(endpointId, iCallback);
         } catch (RemoteException e) {
@@ -869,42 +882,42 @@
     }
 
     /**
-     * Equivalent to {@link #registerEndpointDiscoveryCallback(String,
-     * IHubEndpointDiscoveryCallback, Executor)} with the default executor in the main thread.
+     * Equivalent to {@link #registerEndpointDiscoveryCallback(Executor,
+     * HubEndpointDiscoveryCallback, String)} with the default executor in the main thread.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     public void registerEndpointDiscoveryCallback(
-            @NonNull String serviceDescriptor, @NonNull IHubEndpointDiscoveryCallback callback) {
+            @NonNull HubEndpointDiscoveryCallback callback, @NonNull String serviceDescriptor) {
         registerEndpointDiscoveryCallback(
-                serviceDescriptor, callback, new HandlerExecutor(Handler.getMain()));
+                new HandlerExecutor(Handler.getMain()), callback, serviceDescriptor);
     }
 
     /**
      * Registers a callback to be notified when the hub endpoint with the corresponding service
      * descriptor has started or stopped.
      *
+     * @param executor The executor to invoke the callback on.
      * @param serviceDescriptor The service descriptor of the hub endpoint.
      * @param callback The callback to be invoked.
-     * @param executor The executor to invoke the callback on.
      * @throws IllegalArgumentException if the serviceDescriptor is empty.
      * @throws UnsupportedOperationException If the operation is not supported.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     public void registerEndpointDiscoveryCallback(
-            @NonNull String serviceDescriptor,
-            @NonNull IHubEndpointDiscoveryCallback callback,
-            @NonNull Executor executor) {
-        Objects.requireNonNull(serviceDescriptor, "serviceDescriptor cannot be null");
-        Objects.requireNonNull(callback, "callback cannot be null");
+            @NonNull Executor executor,
+            @NonNull HubEndpointDiscoveryCallback callback,
+            @NonNull String serviceDescriptor) {
         Objects.requireNonNull(executor, "executor cannot be null");
+        Objects.requireNonNull(callback, "callback cannot be null");
+        Objects.requireNonNull(serviceDescriptor, "serviceDescriptor cannot be null");
         if (serviceDescriptor.isBlank()) {
             throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor);
         }
 
         IContextHubEndpointDiscoveryCallback iCallback =
-                createDiscoveryCallback(callback, executor, serviceDescriptor);
+                createDiscoveryCallback(executor, callback, serviceDescriptor);
         try {
             mService.registerEndpointDiscoveryCallbackDescriptor(serviceDescriptor, iCallback);
         } catch (RemoteException e) {
@@ -924,7 +937,7 @@
     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
     @FlaggedApi(Flags.FLAG_OFFLOAD_API)
     public void unregisterEndpointDiscoveryCallback(
-            @NonNull IHubEndpointDiscoveryCallback callback) {
+            @NonNull HubEndpointDiscoveryCallback callback) {
         Objects.requireNonNull(callback, "callback cannot be null");
         IContextHubEndpointDiscoveryCallback iCallback = mDiscoveryCallbacks.remove(callback);
         if (iCallback == null) {
@@ -1291,7 +1304,7 @@
      * service.
      *
      * <p>Context Hub Service will create the endpoint session and notify the registered endpoint.
-     * The registered endpoint will receive callbacks on its {@link IHubEndpointLifecycleCallback}
+     * The registered endpoint will receive callbacks on its {@link HubEndpointLifecycleCallback}
      * object regarding the lifecycle events of the session.
      *
      * @param hubEndpoint {@link HubEndpoint} object previously registered via {@link
@@ -1311,7 +1324,7 @@
      * described by a {@link HubServiceInfo} object.
      *
      * <p>Context Hub Service will create the endpoint session and notify the registered endpoint.
-     * The registered endpoint will receive callbacks on its {@link IHubEndpointLifecycleCallback}
+     * The registered endpoint will receive callbacks on its {@link HubEndpointLifecycleCallback}
      * object regarding the lifecycle events of the session.
      *
      * @param hubEndpoint {@link HubEndpoint} object previously registered via {@link
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index 3425b77..0eb9f29 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -86,8 +86,8 @@
         try {
             checkServerTrustedOcspAndTlsData = tm.getClass().getMethod("checkServerTrusted",
                     X509Certificate[].class,
-                    Byte[].class,
-                    Byte[].class,
+                    byte[].class,
+                    byte[].class,
                     String.class,
                     String.class);
         } catch (ReflectiveOperationException ignored) { }
@@ -179,7 +179,7 @@
         }
         try {
             result = (List<X509Certificate>) mCheckServerTrustedOcspAndTlsData.invoke(mTrustManager,
-                    ocspData, tlsSctData, chain, authType, host);
+                    chain, ocspData, tlsSctData, authType, host);
             return result == null ? Collections.emptyList() : result;
         } catch (IllegalAccessException e) {
             throw new CertificateException("Failed to call checkServerTrusted", e);
diff --git a/core/java/android/net/thread/flags.aconfig b/core/java/android/net/thread/flags.aconfig
index afb982b..100d50d 100644
--- a/core/java/android/net/thread/flags.aconfig
+++ b/core/java/android/net/thread/flags.aconfig
@@ -17,5 +17,5 @@
     is_exported: true
     namespace: "thread_network"
     description: "Controls whether the Android Thread feature is enabled"
-    bug: "301473012"
+    bug: "384596973"
 }
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 5012127..ecd90e4 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -45,7 +45,8 @@
  * {@link PersistableBundle} subclass.
  */
 @android.ravenwood.annotation.RavenwoodKeepWholeClass
-public class BaseBundle {
+@SuppressWarnings("HiddenSuperclass")
+public class BaseBundle implements Parcel.ClassLoaderProvider {
     /** @hide */
     protected static final String TAG = "Bundle";
     static final boolean DEBUG = false;
@@ -299,8 +300,9 @@
 
     /**
      * Return the ClassLoader currently associated with this Bundle.
+     * @hide
      */
-    ClassLoader getClassLoader() {
+    public ClassLoader getClassLoader() {
         return mClassLoader;
     }
 
@@ -405,6 +407,9 @@
             if ((mFlags & Bundle.FLAG_VERIFY_TOKENS_PRESENT) != 0) {
                 Intent.maybeMarkAsMissingCreatorToken(object);
             }
+        } else if (object instanceof Bundle) {
+            Bundle bundle = (Bundle) object;
+            bundle.setClassLoaderSameAsContainerBundleWhenRetrievedFirstTime(this);
         }
         return (clazz != null) ? clazz.cast(object) : (T) object;
     }
@@ -475,10 +480,10 @@
             map.erase();
             map.ensureCapacity(count);
         }
-        int numLazyValues = 0;
+        int[] numLazyValues = new int[]{0};
         try {
-            numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
-                    /* lazy */ ownsParcel, mClassLoader);
+            parcelledData.readArrayMap(map, count, !parcelledByNative,
+                    /* lazy */ ownsParcel, this, numLazyValues);
         } catch (BadParcelableException e) {
             if (sShouldDefuse) {
                 Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -489,14 +494,14 @@
         } finally {
             mWeakParcelledData = null;
             if (ownsParcel) {
-                if (numLazyValues == 0) {
+                if (numLazyValues[0] == 0) {
                     recycleParcel(parcelledData);
                 } else {
                     mWeakParcelledData = new WeakReference<>(parcelledData);
                 }
             }
 
-            mLazyValues = numLazyValues;
+            mLazyValues = numLazyValues[0];
             mParcelledByNative = false;
             mMap = map;
             // Set field last as it is volatile
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 01222cd..18d2afb 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -687,12 +687,18 @@
         return removeFrozenStateChangeCallbackNative(wrappedCallback);
     }
 
+    public static boolean isFrozenStateChangeCallbackSupported() {
+        return isFrozenStateChangeCallbackSupportedNative();
+    }
+
     private native void addFrozenStateChangeCallbackNative(FrozenStateChangeCallback callback)
             throws RemoteException;
 
     private native boolean removeFrozenStateChangeCallbackNative(
             FrozenStateChangeCallback callback);
 
+    private static native boolean isFrozenStateChangeCallbackSupportedNative();
+
     /**
      * Perform a dump on the remote object
      *
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index d54dbad9..c51ad9e 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -431,13 +431,8 @@
          * android.os.Build.VERSION_CODES_FULL}.
          */
         @FlaggedApi(Flags.FLAG_MAJOR_MINOR_VERSIONING_SCHEME)
-        public static final int SDK_INT_FULL;
-
-        static {
-            SDK_INT_FULL = VERSION_CODES_FULL.SDK_INT_MULTIPLIER
-                * SystemProperties.getInt("ro.build.version.sdk", 0)
-                + SystemProperties.getInt("ro.build.version.sdk_minor", 0);
-        }
+        public static final int SDK_INT_FULL = parseFullVersion(SystemProperties.get(
+                    "ro.build.version.sdk_full", ""));
 
         /**
          * The SDK version of the software that <em>initially</em> shipped on
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 819d58d..55bfd45 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -141,6 +141,8 @@
         STRIPPED.putInt("STRIPPED", 1);
     }
 
+    private boolean isFirstRetrievedFromABundle = false;
+
     /**
      * Constructs a new, empty Bundle.
      */
@@ -1020,7 +1022,9 @@
             return null;
         }
         try {
-            return (Bundle) o;
+            Bundle bundle = (Bundle) o;
+            bundle.setClassLoaderSameAsContainerBundleWhenRetrievedFirstTime(this);
+            return bundle;
         } catch (ClassCastException e) {
             typeWarning(key, o, "Bundle", e);
             return null;
@@ -1028,6 +1032,21 @@
     }
 
     /**
+     * Set the ClassLoader of a bundle to its container bundle. This is necessary so that when a
+     * bundle's ClassLoader is changed, it can be propagated to its children. Do this only when it
+     * is retrieved from the container bundle first time though. Once it is accessed outside of its
+     * container, its ClassLoader should no longer be changed by its container anymore.
+     *
+     * @param containerBundle the bundle this bundle is retrieved from.
+     */
+    void setClassLoaderSameAsContainerBundleWhenRetrievedFirstTime(BaseBundle containerBundle) {
+        if (!isFirstRetrievedFromABundle) {
+            setClassLoader(containerBundle.getClassLoader());
+            isFirstRetrievedFromABundle = true;
+        }
+    }
+
+    /**
      * Returns the value associated with the given key, or {@code null} if
      * no mapping of the desired type exists for the given key or a {@code null}
      * value is explicitly associated with the key.
diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl
index 56a089a..5128e91 100644
--- a/core/java/android/os/IHintManager.aidl
+++ b/core/java/android/os/IHintManager.aidl
@@ -39,12 +39,18 @@
      * Throws UnsupportedOperationException if ADPF is not supported, and IllegalStateException
      * if creation is supported but fails.
      */
-    IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag,
+    SessionCreationReturn createHintSessionWithConfig(in IBinder token, in SessionTag tag,
             in SessionCreationConfig creationConfig, out SessionConfig config);
 
     void setHintSessionThreads(in IHintSession hintSession, in int[] tids);
     int[] getHintSessionThreadIds(in IHintSession hintSession);
 
+    parcelable SessionCreationReturn {
+        IHintSession session;
+        // True if the graphics pipeline thread limit is being exceeded
+        boolean pipelineThreadLimitExceeded = false;
+    }
+
     /**
      * Returns FMQ channel information for the caller, which it associates to a binder token.
      *
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 4cac4dee..17697e6 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -22,6 +22,7 @@
 import android.os.PowerSaveState;
 import android.os.WorkSource;
 import android.os.IWakeLockCallback;
+import android.os.IScreenTimeoutPolicyListener;
 
 /** @hide */
 
@@ -45,6 +46,10 @@
     @UnsupportedAppUsage
     boolean isWakeLockLevelSupported(int level);
     boolean isWakeLockLevelSupportedWithDisplayId(int level, int displayId);
+    oneway void addScreenTimeoutPolicyListener(int displayId,
+        IScreenTimeoutPolicyListener listener);
+    oneway void removeScreenTimeoutPolicyListener(int displayId,
+        IScreenTimeoutPolicyListener listener);
 
     void userActivity(int displayId, long time, int event, int flags);
     void wakeUp(long time, int reason, String details, String opPackageName);
diff --git a/nfc/java/android/nfc/INfcVendorNciCallback.aidl b/core/java/android/os/IScreenTimeoutPolicyListener.aidl
similarity index 64%
copy from nfc/java/android/nfc/INfcVendorNciCallback.aidl
copy to core/java/android/os/IScreenTimeoutPolicyListener.aidl
index 821dc6f..62811a0 100644
--- a/nfc/java/android/nfc/INfcVendorNciCallback.aidl
+++ b/core/java/android/os/IScreenTimeoutPolicyListener.aidl
@@ -13,12 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.nfc;
+
+package android.os;
 
 /**
+ * Listener for screen timeout policy changes
+ * @see PowerManager#addScreenTimeoutPolicyListener(int, IScreenTimeoutPolicyListener)
  * @hide
  */
-oneway interface INfcVendorNciCallback {
-    void onVendorResponseReceived(int gid, int oid, in byte[] payload);
-    void onVendorNotificationReceived(int gid, int oid, in byte[] payload);
+oneway interface IScreenTimeoutPolicyListener {
+    /**
+     * @see PowerManager#addScreenTimeoutPolicyListener
+     */
+    oneway void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy);
 }
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index f3bb514..727dcba 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -4,6 +4,8 @@
 
 # PowerManager
 per-file IPowerManager.aidl = file:/services/core/java/com/android/server/power/OWNERS
+per-file IScreenTimeoutPolicyListener.aidl = file:/services/core/java/com/android/server/power/OWNERS
+per-file IWakeLockCallback.aidl = file:/services/core/java/com/android/server/power/OWNERS
 per-file PowerManager.java = file:/services/core/java/com/android/server/power/OWNERS
 per-file PowerManagerInternal.java = file:/services/core/java/com/android/server/power/OWNERS
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index cf473ec..5ba6553 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -4650,7 +4650,7 @@
      * @hide
      */
     @Nullable
-    public Object readLazyValue(@Nullable ClassLoader loader) {
+    private Object readLazyValue(@Nullable ClassLoaderProvider loaderProvider) {
         int start = dataPosition();
         int type = readInt();
         if (isLengthPrefixed(type)) {
@@ -4661,12 +4661,17 @@
             int end = MathUtils.addOrThrow(dataPosition(), objectLength);
             int valueLength = end - start;
             setDataPosition(end);
-            return new LazyValue(this, start, valueLength, type, loader);
+            return new LazyValue(this, start, valueLength, type, loaderProvider);
         } else {
-            return readValue(type, loader, /* clazz */ null);
+            return readValue(type, getClassLoader(loaderProvider), /* clazz */ null);
         }
     }
 
+    @Nullable
+    private static ClassLoader getClassLoader(@Nullable ClassLoaderProvider loaderProvider) {
+        return loaderProvider == null ? null : loaderProvider.getClassLoader();
+    }
+
 
     private static final class LazyValue implements BiFunction<Class<?>, Class<?>[], Object> {
         /**
@@ -4680,7 +4685,12 @@
         private final int mPosition;
         private final int mLength;
         private final int mType;
-        @Nullable private final ClassLoader mLoader;
+        // this member is set when a bundle that includes a LazyValue is unparceled. But it is used
+        // when apply method is called. Between these 2 events, the bundle's ClassLoader could have
+        // changed. Let the bundle be a ClassLoaderProvider allows the bundle provides its current
+        // ClassLoader at the time apply method is called.
+        @NonNull
+        private final ClassLoaderProvider mLoaderProvider;
         @Nullable private Object mObject;
 
         /**
@@ -4691,12 +4701,13 @@
          */
         @Nullable private volatile Parcel mSource;
 
-        LazyValue(Parcel source, int position, int length, int type, @Nullable ClassLoader loader) {
+        LazyValue(Parcel source, int position, int length, int type,
+                @NonNull ClassLoaderProvider loaderProvider) {
             mSource = requireNonNull(source);
             mPosition = position;
             mLength = length;
             mType = type;
-            mLoader = loader;
+            mLoaderProvider = loaderProvider;
         }
 
         @Override
@@ -4709,7 +4720,8 @@
                         int restore = source.dataPosition();
                         try {
                             source.setDataPosition(mPosition);
-                            mObject = source.readValue(mLoader, clazz, itemTypes);
+                            mObject = source.readValue(mLoaderProvider.getClassLoader(), clazz,
+                                    itemTypes);
                         } finally {
                             source.setDataPosition(restore);
                         }
@@ -4782,7 +4794,8 @@
                 return Objects.equals(mObject, value.mObject);
             }
             // Better safely fail here since this could mean we get different objects.
-            if (!Objects.equals(mLoader, value.mLoader)) {
+            if (!Objects.equals(mLoaderProvider.getClassLoader(),
+                    value.mLoaderProvider.getClassLoader())) {
                 return false;
             }
             // Otherwise compare metadata prior to comparing payload.
@@ -4796,10 +4809,24 @@
         @Override
         public int hashCode() {
             // Accessing mSource first to provide memory barrier for mObject
-            return Objects.hash(mSource == null, mObject, mLoader, mType, mLength);
+            return Objects.hash(mSource == null, mObject, mLoaderProvider.getClassLoader(), mType,
+                    mLength);
         }
     }
 
+    /**
+     * Provides a ClassLoader.
+     * @hide
+     */
+    public interface ClassLoaderProvider {
+        /**
+         * Returns a ClassLoader.
+         *
+         * @return ClassLoader
+         */
+        ClassLoader getClassLoader();
+    }
+
     /** Same as {@link #readValue(ClassLoader, Class, Class[])} without any item types. */
     private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz) {
         // Avoids allocating Class[0] array
@@ -5537,8 +5564,8 @@
     }
 
     private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
-            int size, @Nullable ClassLoader loader) {
-        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
+            int size, @Nullable ClassLoaderProvider loaderProvider) {
+        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loaderProvider, null);
     }
 
     /**
@@ -5548,17 +5575,17 @@
      * @param lazy   Whether to populate the map with lazy {@link Function} objects for
      *               length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
      *               details.
-     * @return a count of the lazy values in the map
+     * @param lazyValueCount number of lazy values added here
      * @hide
      */
-    int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
-            boolean lazy, @Nullable ClassLoader loader) {
-        int lazyValues = 0;
+    void readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+            boolean lazy, @Nullable ClassLoaderProvider loaderProvider, int[] lazyValueCount) {
         while (size > 0) {
             String key = readString();
-            Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
+            Object value = (lazy) ? readLazyValue(loaderProvider) : readValue(
+                    getClassLoader(loaderProvider));
             if (value instanceof LazyValue) {
-                lazyValues++;
+                lazyValueCount[0]++;
             }
             if (sorted) {
                 map.append(key, value);
@@ -5570,7 +5597,6 @@
         if (sorted) {
             map.validate();
         }
-        return lazyValues;
     }
 
     /**
@@ -5578,12 +5604,12 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public void readArrayMap(@NonNull ArrayMap<? super String, Object> outVal,
-            @Nullable ClassLoader loader) {
+            @Nullable ClassLoaderProvider loaderProvider) {
         final int N = readInt();
         if (N < 0) {
             return;
         }
-        readArrayMapInternal(outVal, N, loader);
+        readArrayMapInternal(outVal, N, loaderProvider);
     }
 
     /**
diff --git a/core/java/android/os/PerfettoTrace.java b/core/java/android/os/PerfettoTrace.java
new file mode 100644
index 0000000..164561a
--- /dev/null
+++ b/core/java/android/os/PerfettoTrace.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+
+/**
+ * Writes trace events to the perfetto trace buffer. These trace events can be
+ * collected and visualized using the Perfetto UI.
+ *
+ * <p>This tracing mechanism is independent of the method tracing mechanism
+ * offered by {@link Debug#startMethodTracing} or {@link Trace}.
+ *
+ * @hide
+ */
+public final class PerfettoTrace {
+    private static final String TAG = "PerfettoTrace";
+
+    // Keep in sync with C++
+    private static final int PERFETTO_TE_TYPE_SLICE_BEGIN = 1;
+    private static final int PERFETTO_TE_TYPE_SLICE_END = 2;
+    private static final int PERFETTO_TE_TYPE_INSTANT = 3;
+    private static final int PERFETTO_TE_TYPE_COUNTER = 4;
+
+    private static final boolean IS_FLAG_ENABLED = android.os.Flags.perfettoSdkTracingV2();
+
+    /**
+     * For fetching the next flow event id in a process.
+     */
+    private static final AtomicInteger sFlowEventId = new AtomicInteger();
+
+    /**
+     * Perfetto category a trace event belongs to.
+     * Registering a category is not sufficient to capture events within the category, it must
+     * also be enabled in the trace config.
+     */
+    public static final class Category implements PerfettoTrackEventExtra.PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        Category.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+        private final String mName;
+        private final String mTag;
+        private final String mSeverity;
+        private boolean mIsRegistered;
+
+        /**
+         * Category ctor.
+         *
+         * @param name The category name.
+         */
+        public Category(String name) {
+            this(name, null, null);
+        }
+
+        /**
+         * Category ctor.
+         *
+         * @param name The category name.
+         * @param tag An atrace tag name that this category maps to.
+         */
+        public Category(String name, String tag) {
+            this(name, tag, null);
+        }
+
+        /**
+         * Category ctor.
+         *
+         * @param name The category name.
+         * @param tag An atrace tag name that this category maps to.
+         * @param severity A Log style severity string for the category.
+         */
+        public Category(String name, String tag, String severity) {
+            mName = name;
+            mTag = tag;
+            mSeverity = severity;
+            mPtr = native_init(name, tag, severity);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @FastNative
+        private static native long native_init(String name, String tag, String severity);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native void native_register(long ptr);
+        @CriticalNative
+        private static native void native_unregister(long ptr);
+        @CriticalNative
+        private static native boolean native_is_enabled(long ptr);
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+
+        /**
+         * Register the category.
+         */
+        public Category register() {
+            native_register(mPtr);
+            mIsRegistered = true;
+            return this;
+        }
+
+        /**
+         * Unregister the category.
+         */
+        public Category unregister() {
+            native_unregister(mPtr);
+            mIsRegistered = false;
+            return this;
+        }
+
+        /**
+         * Whether the category is enabled or not.
+         */
+        public boolean isEnabled() {
+            return IS_FLAG_ENABLED && native_is_enabled(mPtr);
+        }
+
+        /**
+         * Whether the category is registered or not.
+         */
+        public boolean isRegistered() {
+            return mIsRegistered;
+        }
+
+        /**
+         * Returns the native pointer for the category.
+         */
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+    }
+
+    @FastNative
+    private static native void native_event(int type, long tag, String name, long ptr);
+
+    @CriticalNative
+    private static native long native_get_process_track_uuid();
+
+    @CriticalNative
+    private static native long native_get_thread_track_uuid(long tid);
+
+    @FastNative
+    private static native void native_activate_trigger(String name, int ttlMs);
+
+    /**
+     * Writes a trace message to indicate a given section of code was invoked.
+     *
+     * @param category The perfetto category pointer.
+     * @param eventName The event name to appear in the trace.
+     * @param extra The extra arguments.
+     */
+    public static void instant(Category category, String eventName, PerfettoTrackEventExtra extra) {
+        if (!category.isEnabled()) {
+            return;
+        }
+
+        native_event(PERFETTO_TE_TYPE_INSTANT, category.getPtr(), eventName, extra.getPtr());
+        extra.reset();
+    }
+
+    /**
+     * Writes a trace message to indicate a given section of code was invoked.
+     *
+     * @param category The perfetto category.
+     * @param eventName The event name to appear in the trace.
+     * @param extraConfig Consumer for the extra arguments.
+     */
+    public static void instant(Category category, String eventName,
+            Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
+        PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
+        extraConfig.accept(extra);
+        instant(category, eventName, extra.build());
+    }
+
+    /**
+     * Writes a trace message to indicate a given section of code was invoked.
+     *
+     * @param category The perfetto category.
+     * @param eventName The event name to appear in the trace.
+     */
+    public static void instant(Category category, String eventName) {
+        instant(category, eventName, PerfettoTrackEventExtra.builder().build());
+    }
+
+    /**
+     * Writes a trace message to indicate the start of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param eventName The event name to appear in the trace.
+     * @param extra The extra arguments.
+     */
+    public static void begin(Category category, String eventName, PerfettoTrackEventExtra extra) {
+        if (!category.isEnabled()) {
+            return;
+        }
+
+        native_event(PERFETTO_TE_TYPE_SLICE_BEGIN, category.getPtr(), eventName, extra.getPtr());
+        extra.reset();
+    }
+
+    /**
+     * Writes a trace message to indicate the start of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param eventName The event name to appear in the trace.
+     * @param extraConfig Consumer for the extra arguments.
+     */
+    public static void begin(Category category, String eventName,
+            Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
+        PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
+        extraConfig.accept(extra);
+        begin(category, eventName, extra.build());
+    }
+
+    /**
+     * Writes a trace message to indicate the start of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param eventName The event name to appear in the trace.
+     */
+    public static void begin(Category category, String eventName) {
+        begin(category, eventName, PerfettoTrackEventExtra.builder().build());
+    }
+
+    /**
+     * Writes a trace message to indicate the end of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param extra The extra arguments.
+     */
+    public static void end(Category category, PerfettoTrackEventExtra extra) {
+        if (!category.isEnabled()) {
+            return;
+        }
+
+        native_event(PERFETTO_TE_TYPE_SLICE_END, category.getPtr(), "", extra.getPtr());
+        extra.reset();
+    }
+
+    /**
+     * Writes a trace message to indicate the end of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param extraConfig Consumer for the extra arguments.
+     */
+    public static void end(Category category,
+            Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
+        PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
+        extraConfig.accept(extra);
+        end(category, extra.build());
+    }
+
+    /**
+     * Writes a trace message to indicate the end of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     */
+    public static void end(Category category) {
+        end(category, PerfettoTrackEventExtra.builder().build());
+    }
+
+    /**
+     * Writes a trace message to indicate the value of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param extra The extra arguments.
+     */
+    public static void counter(Category category, PerfettoTrackEventExtra extra) {
+        if (!category.isEnabled()) {
+            return;
+        }
+
+        native_event(PERFETTO_TE_TYPE_COUNTER, category.getPtr(), "", extra.getPtr());
+        extra.reset();
+    }
+
+    /**
+     * Writes a trace message to indicate the value of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param extraConfig Consumer for the extra arguments.
+     */
+    public static void counter(Category category,
+            Consumer<PerfettoTrackEventExtra.Builder> extraConfig) {
+        PerfettoTrackEventExtra.Builder extra = PerfettoTrackEventExtra.builder();
+        extraConfig.accept(extra);
+        counter(category, extra.build());
+    }
+
+    /**
+     * Writes a trace message to indicate the value of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param trackName The trackName for the event.
+     * @param value The value of the counter.
+     */
+    public static void counter(Category category, String trackName, long value) {
+        PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
+                .usingCounterTrack(trackName, PerfettoTrace.getProcessTrackUuid())
+                .setCounter(value)
+                .build();
+        counter(category, extra);
+    }
+
+    /**
+     * Writes a trace message to indicate the value of a given section of code.
+     *
+     * @param category The perfetto category pointer.
+     * @param trackName The trackName for the event.
+     * @param value The value of the counter.
+     */
+    public static void counter(Category category, String trackName, double value) {
+        PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
+                .usingCounterTrack(trackName, PerfettoTrace.getProcessTrackUuid())
+                .setCounter(value)
+                .build();
+        counter(category, extra);
+    }
+
+    /**
+     * Returns the next flow id to be used.
+     */
+    public static int getFlowId() {
+        return sFlowEventId.incrementAndGet();
+    }
+
+    /**
+     * Returns the global track uuid that can be used as a parent track uuid.
+     */
+    public static long getGlobalTrackUuid() {
+        return 0;
+    }
+
+    /**
+     * Returns the process track uuid that can be used as a parent track uuid.
+     */
+    public static long getProcessTrackUuid() {
+        if (IS_FLAG_ENABLED) {
+            return 0;
+        }
+        return native_get_process_track_uuid();
+    }
+
+    /**
+     * Given a thread tid, returns the thread track uuid that can be used as a parent track uuid.
+     */
+    public static long getThreadTrackUuid(long tid) {
+        if (IS_FLAG_ENABLED) {
+            return 0;
+        }
+        return native_get_thread_track_uuid(tid);
+    }
+
+    /**
+     * Activates a trigger by name {@code triggerName} with expiry in {@code ttlMs}.
+     */
+    public static void activateTrigger(String triggerName, int ttlMs) {
+        if (IS_FLAG_ENABLED) {
+            return;
+        }
+        native_activate_trigger(triggerName, ttlMs);
+    }
+
+    /**
+     * Registers the process with Perfetto.
+     */
+    public static void register() {
+        Trace.registerWithPerfetto();
+    }
+}
diff --git a/core/java/android/os/PerfettoTrackEventExtra.java b/core/java/android/os/PerfettoTrackEventExtra.java
new file mode 100644
index 0000000..a219b3b
--- /dev/null
+++ b/core/java/android/os/PerfettoTrackEventExtra.java
@@ -0,0 +1,1081 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
+import libcore.util.NativeAllocationRegistry;
+
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
+
+/**
+ * Holds extras to be passed to Perfetto track events in {@link PerfettoTrace}.
+ *
+ * @hide
+ */
+public final class PerfettoTrackEventExtra {
+    private static final int DEFAULT_EXTRA_CACHE_SIZE = 5;
+    private static final ThreadLocal<PerfettoTrackEventExtra> sTrackEventExtra =
+            new ThreadLocal<PerfettoTrackEventExtra>() {
+                @Override
+                protected PerfettoTrackEventExtra initialValue() {
+                    return new PerfettoTrackEventExtra();
+                }
+            };
+    private static final AtomicLong sNamedTrackId = new AtomicLong();
+
+    private boolean mIsInUse;
+    private CounterInt64 mCounterInt64;
+    private CounterDouble mCounterDouble;
+    private Proto mProto;
+
+    /**
+     * Represents a native pointer to a Perfetto C SDK struct. E.g. PerfettoTeHlExtra.
+     */
+    public interface PerfettoPointer {
+        /**
+         * Returns the perfetto struct native pointer.
+         */
+        long getPtr();
+    }
+
+    /**
+     * Container for {@link Field} instances.
+     */
+    public interface FieldContainer {
+        /**
+         * Add {@link Field} to the container.
+         */
+        void addField(PerfettoPointer field);
+    }
+
+    /**
+     * RingBuffer implemented on top of a SparseArray.
+     *
+     * Bounds a SparseArray with a FIFO algorithm.
+     */
+    private static final class RingBuffer<T> {
+        private final int mCapacity;
+        private final int[] mKeyArray;
+        private final T[] mValueArray;
+        private int mWriteEnd = 0;
+
+        RingBuffer(int capacity) {
+            mCapacity = capacity;
+            mKeyArray = new int[capacity];
+            mValueArray = (T[]) new Object[capacity];
+        }
+
+        public void put(int key, T value) {
+            mKeyArray[mWriteEnd] = key;
+            mValueArray[mWriteEnd] = value;
+            mWriteEnd = (mWriteEnd + 1) % mCapacity;
+        }
+
+        public T get(int key) {
+            for (int i = 0; i < mCapacity; i++) {
+                if (mKeyArray[i] == key) {
+                    return mValueArray[i];
+                }
+            }
+            return null;
+        }
+    }
+
+    private static final class Pool<T> {
+        private final int mCapacity;
+        private final T[] mValueArray;
+        private int mIdx = 0;
+
+        Pool(int capacity) {
+            mCapacity = capacity;
+            mValueArray = (T[]) new Object[capacity];
+        }
+
+        public void reset() {
+            mIdx = 0;
+        }
+
+        public T get(Supplier<T> supplier) {
+            if (mIdx >= mCapacity) {
+                return supplier.get();
+            }
+            if (mValueArray[mIdx] == null) {
+                mValueArray[mIdx] = supplier.get();
+            }
+            return mValueArray[mIdx++];
+        }
+    }
+
+    /**
+     * Builder for Perfetto track event extras.
+     */
+    public static final class Builder {
+        // For performance reasons, we hold a reference to mExtra as a holder for
+        // perfetto pointers being added. This way, we avoid an additional list to hold
+        // the pointers in Java and we can pass them down directly to native code.
+        private final PerfettoTrackEventExtra mExtra;
+        private boolean mIsBuilt;
+        private Builder mParent;
+        private FieldContainer mCurrentContainer;
+
+        private final CounterInt64 mCounterInt64;
+        private final CounterDouble mCounterDouble;
+        private final Proto mProto;
+
+        private final RingBuffer<NamedTrack> mNamedTrackCache;
+        private final RingBuffer<CounterTrack> mCounterTrackCache;
+        private final RingBuffer<ArgInt64> mArgInt64Cache;
+        private final RingBuffer<ArgBool> mArgBoolCache;
+        private final RingBuffer<ArgDouble> mArgDoubleCache;
+        private final RingBuffer<ArgString> mArgStringCache;
+
+        private final Pool<FieldInt64> mFieldInt64Cache;
+        private final Pool<FieldDouble> mFieldDoubleCache;
+        private final Pool<FieldString> mFieldStringCache;
+        private final Pool<FieldNested> mFieldNestedCache;
+        private final Pool<Flow> mFlowCache;
+        private final Pool<Builder> mBuilderCache;
+
+        private Builder() {
+            this(sTrackEventExtra.get(), null, null);
+        }
+
+        private Builder(PerfettoTrackEventExtra extra, Builder parent, FieldContainer container) {
+            mExtra = extra;
+            mParent = parent;
+            mCurrentContainer = container;
+
+            mNamedTrackCache = mExtra.mNamedTrackCache;
+            mCounterTrackCache = mExtra.mCounterTrackCache;
+            mArgInt64Cache = mExtra.mArgInt64Cache;
+            mArgDoubleCache = mExtra.mArgDoubleCache;
+            mArgBoolCache = mExtra.mArgBoolCache;
+            mArgStringCache = mExtra.mArgStringCache;
+            mFieldInt64Cache = mExtra.mFieldInt64Cache;
+            mFieldDoubleCache = mExtra.mFieldDoubleCache;
+            mFieldStringCache = mExtra.mFieldStringCache;
+            mFieldNestedCache = mExtra.mFieldNestedCache;
+            mFlowCache = mExtra.mFlowCache;
+            mBuilderCache = mExtra.mBuilderCache;
+
+            mCounterInt64 = mExtra.getCounterInt64();
+            mCounterDouble = mExtra.getCounterDouble();
+            mProto = mExtra.getProto();
+        }
+
+        /**
+         * Builds the track event extra.
+         */
+        public PerfettoTrackEventExtra build() {
+            checkParent();
+            mIsBuilt = true;
+
+            mFieldInt64Cache.reset();
+            mFieldDoubleCache.reset();
+            mFieldStringCache.reset();
+            mFieldNestedCache.reset();
+            mBuilderCache.reset();
+
+            return mExtra;
+        }
+
+        /**
+         * Adds a debug arg with key {@code name} and value {@code val}.
+         */
+        public Builder addArg(String name, long val) {
+            checkParent();
+            ArgInt64 arg = mArgInt64Cache.get(name.hashCode());
+            if (arg == null || !arg.getName().equals(name)) {
+                arg = new ArgInt64(name);
+                mArgInt64Cache.put(name.hashCode(), arg);
+            }
+            arg.setValue(val);
+            mExtra.addPerfettoPointer(arg);
+            return this;
+        }
+
+        /**
+         * Adds a debug arg with key {@code name} and value {@code val}.
+         */
+        public Builder addArg(String name, boolean val) {
+            checkParent();
+            ArgBool arg = mArgBoolCache.get(name.hashCode());
+            if (arg == null || !arg.getName().equals(name)) {
+                arg = new ArgBool(name);
+                mArgBoolCache.put(name.hashCode(), arg);
+            }
+            arg.setValue(val);
+            mExtra.addPerfettoPointer(arg);
+            return this;
+        }
+
+        /**
+         * Adds a debug arg with key {@code name} and value {@code val}.
+         */
+        public Builder addArg(String name, double val) {
+            checkParent();
+            ArgDouble arg = mArgDoubleCache.get(name.hashCode());
+            if (arg == null || !arg.getName().equals(name)) {
+                arg = new ArgDouble(name);
+                mArgDoubleCache.put(name.hashCode(), arg);
+            }
+            arg.setValue(val);
+            mExtra.addPerfettoPointer(arg);
+            return this;
+        }
+
+        /**
+         * Adds a debug arg with key {@code name} and value {@code val}.
+         */
+        public Builder addArg(String name, String val) {
+            checkParent();
+            ArgString arg = mArgStringCache.get(name.hashCode());
+            if (arg == null || !arg.getName().equals(name)) {
+                arg = new ArgString(name);
+                mArgStringCache.put(name.hashCode(), arg);
+            }
+            arg.setValue(val);
+            mExtra.addPerfettoPointer(arg);
+            return this;
+        }
+
+        /**
+         * Adds a flow with {@code id}.
+         */
+        public Builder addFlow(int id) {
+            checkParent();
+            Flow flow = mFlowCache.get(Flow::new);
+            flow.setProcessFlow(id);
+            mExtra.addPerfettoPointer(flow);
+            return this;
+        }
+
+        /**
+         * Adds a terminating flow with {@code id}.
+         */
+        public Builder addTerminatingFlow(int id) {
+            checkParent();
+            Flow flow = mFlowCache.get(Flow::new);
+            flow.setProcessTerminatingFlow(id);
+            mExtra.addPerfettoPointer(flow);
+            return this;
+        }
+
+        /**
+         * Adds the events to a named track instead of the thread track where the
+         * event occurred.
+         */
+        public Builder usingNamedTrack(String name, long parentUuid) {
+            checkParent();
+            NamedTrack track = mNamedTrackCache.get(name.hashCode());
+            if (track == null || !track.getName().equals(name)) {
+                track = new NamedTrack(name, parentUuid);
+                mNamedTrackCache.put(name.hashCode(), track);
+            }
+            mExtra.addPerfettoPointer(track);
+            return this;
+        }
+
+        /**
+         * Adds the events to a counter track instead. This is required for
+         * setting counter values.
+         *
+         */
+        public Builder usingCounterTrack(String name, long parentUuid) {
+            checkParent();
+            CounterTrack track = mCounterTrackCache.get(name.hashCode());
+            if (track == null || !track.getName().equals(name)) {
+                track = new CounterTrack(name, parentUuid);
+                mCounterTrackCache.put(name.hashCode(), track);
+            }
+            mExtra.addPerfettoPointer(track);
+            return this;
+        }
+
+        /**
+         * Sets a long counter value on the event.
+         *
+         */
+        public Builder setCounter(long val) {
+            checkParent();
+            mCounterInt64.setValue(val);
+            mExtra.addPerfettoPointer(mCounterInt64);
+            return this;
+        }
+
+        /**
+         * Sets a double counter value on the event.
+         *
+         */
+        public Builder setCounter(double val) {
+            checkParent();
+            mCounterDouble.setValue(val);
+            mExtra.addPerfettoPointer(mCounterDouble);
+            return this;
+        }
+
+        /**
+         * Adds a proto field with field id {@code id} and value {@code val}.
+         */
+        public Builder addField(long id, long val) {
+            checkContainer();
+            FieldInt64 field = mFieldInt64Cache.get(FieldInt64::new);
+            field.setValue(id, val);
+            mCurrentContainer.addField(field);
+            return this;
+        }
+
+        /**
+         * Adds a proto field with field id {@code id} and value {@code val}.
+         */
+        public Builder addField(long id, double val) {
+            checkContainer();
+            FieldDouble field = mFieldDoubleCache.get(FieldDouble::new);
+            field.setValue(id, val);
+            mCurrentContainer.addField(field);
+            return this;
+        }
+
+        /**
+         * Adds a proto field with field id {@code id} and value {@code val}.
+         */
+        public Builder addField(long id, String val) {
+            checkContainer();
+            FieldString field = mFieldStringCache.get(FieldString::new);
+            field.setValue(id, val);
+            mCurrentContainer.addField(field);
+            return this;
+        }
+
+        /**
+         * Begins a proto field with field
+         * Fields can be added from this point and there must be a corresponding
+         * {@link endProto}.
+         *
+         * The proto field is a singleton and all proto fields get added inside the
+         * one {@link beginProto} and {@link endProto} within the {@link Builder}.
+         */
+        public Builder beginProto() {
+            checkParent();
+            mProto.clearFields();
+            mExtra.addPerfettoPointer(mProto);
+            return mBuilderCache.get(Builder::new).init(this, mProto);
+        }
+
+        /**
+         * Ends a proto field.
+         */
+        public Builder endProto() {
+            if (mParent == null || mCurrentContainer == null) {
+                throw new IllegalStateException("No proto to end");
+            }
+            return mParent;
+        }
+
+        /**
+         * Begins a nested proto field with field id {@code id}.
+         * Fields can be added from this point and there must be a corresponding
+         * {@link endNested}.
+         */
+        public Builder beginNested(long id) {
+            checkContainer();
+            FieldNested field = mFieldNestedCache.get(FieldNested::new);
+            field.setId(id);
+            mCurrentContainer.addField(field);
+            return mBuilderCache.get(Builder::new).init(this, field);
+        }
+
+        /**
+         * Ends a nested proto field.
+         */
+        public Builder endNested() {
+            if (mParent == null || mCurrentContainer == null) {
+                throw new IllegalStateException("No nested field to end");
+            }
+            return mParent;
+        }
+
+        /**
+         * Initializes a {@link Builder}.
+         */
+        public Builder init(Builder parent, FieldContainer container) {
+            mParent = parent;
+            mCurrentContainer = container;
+            mIsBuilt = false;
+
+            if (mParent == null) {
+                if (mExtra.mIsInUse) {
+                    throw new IllegalStateException("Cannot create a new builder when another"
+                            + " extra is in use");
+                }
+                mExtra.mIsInUse = true;
+            }
+            return this;
+        }
+
+        private void checkState() {
+            if (mIsBuilt) {
+                throw new IllegalStateException(
+                    "This builder has already been used. Create a new builder for another event.");
+            }
+        }
+
+        private void checkParent() {
+            checkState();
+            if (mParent != null) {
+                throw new IllegalStateException(
+                    "This builder has already been used. Create a new builder for another event.");
+            }
+        }
+
+        private void checkContainer() {
+            checkState();
+            if (mCurrentContainer == null) {
+                throw new IllegalStateException(
+                    "Field operations must be within beginProto/endProto block");
+            }
+        }
+    }
+
+    /**
+     * Start a {@link Builder} to build a {@link PerfettoTrackEventExtra}.
+     */
+    public static Builder builder() {
+        return sTrackEventExtra.get().mBuilderCache.get(Builder::new).init(null, null);
+    }
+
+    private final RingBuffer<NamedTrack> mNamedTrackCache =
+            new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+    private final RingBuffer<CounterTrack> mCounterTrackCache =
+            new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+
+    private final RingBuffer<ArgInt64> mArgInt64Cache = new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+    private final RingBuffer<ArgBool> mArgBoolCache = new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+    private final RingBuffer<ArgDouble> mArgDoubleCache = new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+    private final RingBuffer<ArgString> mArgStringCache = new RingBuffer(DEFAULT_EXTRA_CACHE_SIZE);
+
+    private final Pool<FieldInt64> mFieldInt64Cache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+    private final Pool<FieldDouble> mFieldDoubleCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+    private final Pool<FieldString> mFieldStringCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+    private final Pool<FieldNested> mFieldNestedCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+    private final Pool<Flow> mFlowCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+    private final Pool<Builder> mBuilderCache = new Pool(DEFAULT_EXTRA_CACHE_SIZE);
+
+    private static final NativeAllocationRegistry sRegistry =
+            NativeAllocationRegistry.createMalloced(
+                    PerfettoTrackEventExtra.class.getClassLoader(), native_delete());
+
+    private final long mPtr;
+    private static final String TAG = "PerfettoTrackEventExtra";
+
+    private PerfettoTrackEventExtra() {
+        mPtr = native_init();
+        sRegistry.registerNativeAllocation(this, mPtr);
+    }
+
+    /**
+     * Returns the native pointer.
+     */
+    public long getPtr() {
+        return mPtr;
+    }
+
+    /**
+     * Adds a pointer representing a track event parameter.
+     */
+    public void addPerfettoPointer(PerfettoPointer extra) {
+        native_add_arg(mPtr, extra.getPtr());
+    }
+
+    /**
+     * Resets the track event extra.
+     */
+    public void reset() {
+        native_clear_args(mPtr);
+        mIsInUse = false;
+    }
+
+    private CounterInt64 getCounterInt64() {
+        if (mCounterInt64 == null) {
+            mCounterInt64 = new CounterInt64();
+        }
+        return mCounterInt64;
+    }
+
+    private CounterDouble getCounterDouble() {
+        if (mCounterDouble == null) {
+            mCounterDouble = new CounterDouble();
+        }
+        return mCounterDouble;
+    }
+
+    private Proto getProto() {
+        if (mProto == null) {
+            mProto = new Proto();
+        }
+        return mProto;
+    }
+
+    private static final class Flow implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        Flow.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+
+        Flow() {
+            mPtr = native_init();
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        public void setProcessFlow(long type) {
+            native_set_process_flow(mPtr, type);
+        }
+
+        public void setProcessTerminatingFlow(long id) {
+            native_set_process_terminating_flow(mPtr, id);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native void native_set_process_flow(long ptr, long type);
+        @CriticalNative
+        private static native void native_set_process_terminating_flow(long ptr, long id);
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+    }
+
+    private static class NamedTrack implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        NamedTrack.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+        private final String mName;
+
+        NamedTrack(String name, long parentUuid) {
+            mPtr = native_init(sNamedTrackId.incrementAndGet(), name, parentUuid);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        @FastNative
+        private static native long native_init(long id, String name, long parentUuid);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+    }
+
+    private static final class CounterTrack implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        CounterTrack.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+        private final String mName;
+
+        CounterTrack(String name, long parentUuid) {
+            mPtr = native_init(name, parentUuid);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        @FastNative
+        private static native long native_init(String name, long parentUuid);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+    }
+
+    private static final class CounterInt64 implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        CounterInt64.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+
+        CounterInt64() {
+            mPtr = native_init();
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public void setValue(long value) {
+            native_set_value(mPtr, value);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native void native_set_value(long ptr, long value);
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+    }
+
+    private static final class CounterDouble implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        CounterDouble.class.getClassLoader(), native_delete());
+
+        private final long mPtr;
+        private final long mExtraPtr;
+
+        CounterDouble() {
+            mPtr = native_init();
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public void setValue(double value) {
+            native_set_value(mPtr, value);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native void native_set_value(long ptr, double value);
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+    }
+
+    private static final class ArgInt64 implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        ArgInt64.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mExtraPtr;
+
+        private final String mName;
+
+        ArgInt64(String name) {
+            mPtr = native_init(name);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public void setValue(long val) {
+            native_set_value(mPtr, val);
+        }
+
+        @FastNative
+        private static native long native_init(String name);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_set_value(long ptr, long val);
+    }
+
+    private static final class ArgBool implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        ArgBool.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mExtraPtr;
+
+        private final String mName;
+
+        ArgBool(String name) {
+            mPtr = native_init(name);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public void setValue(boolean val) {
+            native_set_value(mPtr, val);
+        }
+
+        @FastNative
+        private static native long native_init(String name);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_set_value(long ptr, boolean val);
+    }
+
+    private static final class ArgDouble implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        ArgDouble.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mExtraPtr;
+
+        private final String mName;
+
+        ArgDouble(String name) {
+            mPtr = native_init(name);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public void setValue(double val) {
+            native_set_value(mPtr, val);
+        }
+
+        @FastNative
+        private static native long native_init(String name);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_set_value(long ptr, double val);
+    }
+
+    private static final class ArgString implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        ArgString.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mExtraPtr;
+
+        private final String mName;
+
+        ArgString(String name) {
+            mPtr = native_init(name);
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            mName = name;
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        public String getName() {
+            return mName;
+        }
+
+        public void setValue(String val) {
+            native_set_value(mPtr, val);
+        }
+
+        @FastNative
+        private static native long native_init(String name);
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @FastNative
+        private static native void native_set_value(long ptr, String val);
+    }
+
+    private static final class Proto implements PerfettoPointer, FieldContainer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        Proto.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mExtraPtr;
+
+        Proto() {
+            mPtr = native_init();
+            mExtraPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mExtraPtr;
+        }
+
+        @Override
+        public void addField(PerfettoPointer field) {
+            native_add_field(mPtr, field.getPtr());
+        }
+
+        public void clearFields() {
+            native_clear_fields(mPtr);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_add_field(long ptr, long extraPtr);
+        @CriticalNative
+        private static native void native_clear_fields(long ptr);
+    }
+
+    private static final class FieldInt64 implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        FieldInt64.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mFieldPtr;
+
+        FieldInt64() {
+            mPtr = native_init();
+            mFieldPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mFieldPtr;
+        }
+
+        public void setValue(long id, long val) {
+            native_set_value(mPtr, id, val);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_set_value(long ptr, long id, long val);
+    }
+
+    private static final class FieldDouble implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        FieldDouble.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mFieldPtr;
+
+        FieldDouble() {
+            mPtr = native_init();
+            mFieldPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mFieldPtr;
+        }
+
+        public void setValue(long id, double val) {
+            native_set_value(mPtr, id, val);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_set_value(long ptr, long id, double val);
+    }
+
+    private static final class FieldString implements PerfettoPointer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        FieldString.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mFieldPtr;
+
+        FieldString() {
+            mPtr = native_init();
+            mFieldPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mFieldPtr;
+        }
+
+        public void setValue(long id, String val) {
+            native_set_value(mPtr, id, val);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @FastNative
+        private static native void native_set_value(long ptr, long id, String val);
+    }
+
+    private static final class FieldNested implements PerfettoPointer, FieldContainer {
+        private static final NativeAllocationRegistry sRegistry =
+                NativeAllocationRegistry.createMalloced(
+                        FieldNested.class.getClassLoader(), native_delete());
+
+        // Private pointer holding Perfetto object with metadata
+        private final long mPtr;
+
+        // Public pointer to Perfetto object itself
+        private final long mFieldPtr;
+
+        FieldNested() {
+            mPtr = native_init();
+            mFieldPtr = native_get_extra_ptr(mPtr);
+            sRegistry.registerNativeAllocation(this, mPtr);
+        }
+
+        @Override
+        public long getPtr() {
+            return mFieldPtr;
+        }
+
+        @Override
+        public void addField(PerfettoPointer field) {
+            native_add_field(mPtr, field.getPtr());
+        }
+
+        public void setId(long id) {
+            native_set_id(mPtr, id);
+        }
+
+        @CriticalNative
+        private static native long native_init();
+        @CriticalNative
+        private static native long native_delete();
+        @CriticalNative
+        private static native long native_get_extra_ptr(long ptr);
+        @CriticalNative
+        private static native void native_add_field(long ptr, long extraPtr);
+        @CriticalNative
+        private static native void native_set_id(long ptr, long id);
+    }
+
+    @CriticalNative
+    private static native long native_init();
+    @CriticalNative
+    private static native long native_delete();
+    @CriticalNative
+    private static native void native_add_arg(long ptr, long extraPtr);
+    @CriticalNative
+    private static native void native_clear_args(long ptr);
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cd48f08..1801df0 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -34,6 +34,7 @@
 import android.app.PropertyInvalidatedCache;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.os.IScreenTimeoutPolicyListener;
 import android.service.dreams.Sandman;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -1049,6 +1050,29 @@
     }
 
     /**
+     * Screen timeout policy type: the screen turns off after a timeout
+     * @hide
+     */
+    public static final int SCREEN_TIMEOUT_ACTIVE = 0;
+
+    /**
+     * Screen timeout policy type: the screen is kept 'on' (no timeout)
+     * @hide
+     */
+    public static final int SCREEN_TIMEOUT_KEEP_DISPLAY_ON = 1;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "SCREEN_TIMEOUT_" }, value = {
+            SCREEN_TIMEOUT_ACTIVE,
+            SCREEN_TIMEOUT_KEEP_DISPLAY_ON
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScreenTimeoutPolicy{}
+
+
+    /**
      * Either the location providers shouldn't be affected by battery saver,
      * or battery saver is off.
      */
@@ -1208,6 +1232,9 @@
     private final ArrayMap<OnThermalHeadroomChangedListener, IThermalHeadroomListener>
             mThermalHeadroomListenerMap = new ArrayMap<>();
 
+    private final ArrayMap<ScreenTimeoutPolicyListener, IScreenTimeoutPolicyListener>
+            mScreenTimeoutPolicyListeners = new ArrayMap<>();
+
     /**
      * {@hide}
      */
@@ -1749,6 +1776,77 @@
         }
     }
 
+    /**
+     * Adds a listener to be notified about changes in screen timeout policy.
+     *
+     * <p>The screen timeout policy determines the behavior of the device's screen
+     * after a period of inactivity. It can be used to understand if the display is going
+     * to be turned off after a timeout to conserve power, or if it will be kept on indefinitely.
+     * For example, it might be useful for adjusting display switch conditions on foldable
+     * devices based on the current timeout policy.
+     *
+     * <p>See {@link ScreenTimeoutPolicy} for possible values.
+     *
+     * <p>The listener will be fired with the initial state upon subscribing.
+     *
+     * <p>IScreenTimeoutPolicyListener is called on either system server's main thread or
+     * on a binder thread if subscribed outside the system service process.
+     *
+     * @param displayId display id for which to be notified about screen timeout policy changes
+     * @param executor executor on which to execute ScreenTimeoutPolicyListener methods
+     * @param listener listener that will be fired on screem timeout policy updates
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
+    public void addScreenTimeoutPolicyListener(int displayId,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull ScreenTimeoutPolicyListener listener) {
+        Objects.requireNonNull(listener, "listener cannot be null");
+        Objects.requireNonNull(executor, "executor cannot be null");
+        Preconditions.checkArgument(!mScreenTimeoutPolicyListeners.containsKey(listener),
+                "Listener already registered: %s", listener);
+
+        final IScreenTimeoutPolicyListener stub = new IScreenTimeoutPolicyListener.Stub() {
+            public void onScreenTimeoutPolicyChanged(int screenTimeoutPolicy) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(() ->
+                            listener.onScreenTimeoutPolicyChanged(screenTimeoutPolicy));
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        };
+
+        try {
+            mService.addScreenTimeoutPolicyListener(displayId, stub);
+            mScreenTimeoutPolicyListeners.put(listener, stub);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Removes a listener that is used to listen for screen timeout policy changes.
+     * @see PowerManager#addScreenTimeoutPolicyListener(int, ScreenTimeoutPolicyListener)
+     * @param displayId display id for which to be notified about screen timeout changes
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
+    public void removeScreenTimeoutPolicyListener(int displayId,
+            @NonNull ScreenTimeoutPolicyListener listener) {
+        Objects.requireNonNull(listener, "listener cannot be null");
+        IScreenTimeoutPolicyListener internalListener = mScreenTimeoutPolicyListeners.get(listener);
+        Preconditions.checkArgument(internalListener != null, "Listener was not added");
+
+        try {
+            mService.removeScreenTimeoutPolicyListener(displayId, internalListener);
+            mScreenTimeoutPolicyListeners.remove(listener);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
    /**
      * Returns true if the specified wake lock level is supported.
      *
@@ -3825,6 +3923,21 @@
     }
 
     /**
+     * Listener for screen timeout policy changes
+     * @see PowerManager#addScreenTimeoutPolicyListener(int, ScreenTimeoutPolicyListener)
+     * @hide
+     */
+    public interface ScreenTimeoutPolicyListener {
+        /**
+         * Invoked on changes in screen timeout policy.
+         *
+         * @param screenTimeoutPolicy Screen timeout policy, one of {@link ScreenTimeoutPolicy}
+         * @see PowerManager#addScreenTimeoutPolicyListener
+         */
+        void onScreenTimeoutPolicyChanged(@ScreenTimeoutPolicy int screenTimeoutPolicy);
+    }
+
+    /**
      * A wake lock is a mechanism to indicate that your application needs
      * to have the device stay on.
      * <p>
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 907d968..0c5d9e97 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1221,6 +1221,17 @@
      */
     public static final native int[] getExclusiveCores();
 
+
+    /**
+     * Get the CPU affinity masks from sched_getaffinity.
+     *
+     * @param tid The identifier of the thread/process to get the sched affinity.
+     * @return an array of CPU affinity masks, of which the size will be dynamic and just enough to
+     *         include all bit masks for all currently online and possible CPUs of the device.
+     * @hide
+     */
+    public static final native long[] getSchedAffinity(int tid);
+
     /**
      * Set the priority of the calling thread, based on Linux priorities.  See
      * {@link #setThreadPriority(int, int)} for more information.
diff --git a/core/java/android/os/TestLooperManager.java b/core/java/android/os/TestLooperManager.java
index e216992..289b98c 100644
--- a/core/java/android/os/TestLooperManager.java
+++ b/core/java/android/os/TestLooperManager.java
@@ -41,6 +41,7 @@
 
     private boolean mReleased;
     private boolean mLooperBlocked;
+    private final boolean mLooperIsMyLooper;
 
     /**
      * @hide
@@ -54,8 +55,11 @@
         }
         mLooper = looper;
         mQueue = mLooper.getQueue();
-        // Post a message that will keep the looper blocked as long as we are dispatching.
-        new Handler(looper).post(new LooperHolder());
+        mLooperIsMyLooper = Looper.myLooper() == looper;
+        if (!mLooperIsMyLooper) {
+            // Post a message that will keep the looper blocked as long as we are dispatching.
+            new Handler(looper).post(new LooperHolder());
+        }
     }
 
     /**
@@ -82,7 +86,7 @@
     public Message next() {
         // Wait for the looper block to come up, to make sure we don't accidentally get
         // the message for the block.
-        while (!mLooperBlocked) {
+        while (!mLooperIsMyLooper && !mLooperBlocked) {
             synchronized (this) {
                 try {
                     wait();
@@ -114,9 +118,6 @@
      * should be executed by this queue.
      * If the queue is empty or no messages are deliverable, returns null.
      * This method never blocks.
-     *
-     * <p>Callers should always call {@link #recycle(Message)} on the message when all interactions
-     * with it have completed.
      */
     @FlaggedApi(Flags.FLAG_MESSAGE_QUEUE_TESTABILITY)
     @SuppressWarnings("AutoBoxing")  // box the primitive long, or return null to indicate no value
@@ -165,6 +166,9 @@
             // This is being called from the thread it should be executed on, we can just dispatch.
             message.target.dispatchMessage(message);
         } else {
+            if (mLooperIsMyLooper) {
+                throw new RuntimeException("Cannot call execute from non Looper thread");
+            }
             MessageExecution execution = new MessageExecution();
             execution.m = message;
             synchronized (execution) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 132805d..08f68f1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -940,10 +940,10 @@
 
     /**
      * Specifies if a user is disallowed from resetting network settings
-     * from Settings. This can only be set by device owners and profile owners on the primary user.
+     * from Settings. This can only be set by device owners and profile owners on the main user.
      * The default value is <code>false</code>.
-     * <p>This restriction has no effect on secondary users and managed profiles since only the
-     * primary user can reset the network settings of the device.
+     * <p>This restriction has no effect on non-Admin users since they cannot reset the network
+     * settings of the device.
      *
      * <p>Holders of the permission
      * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MOBILE_NETWORK}
@@ -1077,11 +1077,11 @@
     /**
      * Specifies if a user is disallowed from configuring cell broadcasts.
      *
-     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * <p>This restriction can only be set by a device owner, a profile owner on the main
      * user or a profile owner of an organization-owned managed profile on the parent profile.
      * When it is set by a device owner, it applies globally. When it is set by a profile owner
-     * on the primary user or by a profile owner of an organization-owned managed profile on
-     * the parent profile, it disables the primary user from configuring cell broadcasts.
+     * on the main user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the user from configuring cell broadcasts.
      *
      * <p>Holders of the permission
      * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MOBILE_NETWORK}
@@ -1089,8 +1089,8 @@
      *
      * <p>The default value is <code>false</code>.
      *
-     * <p>This restriction has no effect on secondary users and managed profiles since only the
-     * primary user can configure cell broadcasts.
+     * <p>This restriction has no effect on non-Admin users since they cannot configure cell
+     * broadcasts.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -1103,11 +1103,11 @@
     /**
      * Specifies if a user is disallowed from configuring mobile networks.
      *
-     * <p>This restriction can only be set by a device owner, a profile owner on the primary
+     * <p>This restriction can only be set by a device owner, a profile owner on the main
      * user or a profile owner of an organization-owned managed profile on the parent profile.
      * When it is set by a device owner, it applies globally. When it is set by a profile owner
-     * on the primary user or by a profile owner of an organization-owned managed profile on
-     * the parent profile, it disables the primary user from configuring mobile networks.
+     * on the main user or by a profile owner of an organization-owned managed profile on
+     * the parent profile, it disables the user from configuring mobile networks.
      *
      * <p>Holders of the permission
      * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MOBILE_NETWORK}
@@ -1115,8 +1115,8 @@
      *
      * <p>The default value is <code>false</code>.
      *
-     * <p>This restriction has no effect on secondary users and managed profiles since only the
-     * primary user can configure mobile networks.
+     * <p>This restriction has no effect on non-Admin users since they cannot configure mobile
+     * networks.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
@@ -4206,12 +4206,16 @@
     private boolean getUserRestrictionFromQuery(@NonNull Pair<String, Integer> restrictionPerUser) {
         return UserManagerCache.getUserRestrictionFromQuery(
                 (Pair<String, Integer> q) -> mService.hasUserRestriction(q.first, q.second),
+                // bypass cache if the flag is disabled
+                (Pair<String, Integer> q) -> !android.multiuser.Flags.cacheUserRestrictionsReadOnly(),
                 restrictionPerUser);
     }
 
     /** @hide */
     public static final void invalidateUserRestriction() {
-        UserManagerCache.invalidateUserRestrictionFromQuery();
+        if (android.multiuser.Flags.cacheUserRestrictionsReadOnly()) {
+            UserManagerCache.invalidateUserRestrictionFromQuery();
+        }
     }
 
     /**
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index 2a46738..e24f08b 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -340,6 +340,13 @@
 
 flag {
      namespace: "system_performance"
+     name: "perfetto_sdk_tracing_v2"
+     description: "Tracing using Perfetto SDK API."
+     bug: "303199244"
+}
+
+flag {
+     namespace: "system_performance"
      name: "telemetry_apis_framework_initialization"
      is_exported: true
      description: "Control framework initialization APIs of telemetry APIs feature."
diff --git a/core/java/android/provider/BlockedNumbersManager.java b/core/java/android/provider/BlockedNumbersManager.java
index aee396d..a0dc176 100644
--- a/core/java/android/provider/BlockedNumbersManager.java
+++ b/core/java/android/provider/BlockedNumbersManager.java
@@ -357,7 +357,7 @@
          */
         private long mUntilTimestampMillis;
 
-        public BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) {
+        BlockSuppressionStatus(boolean isSuppressed, long untilTimestampMillis) {
             this.mIsSuppressed = isSuppressed;
             this.mUntilTimestampMillis = untilTimestampMillis;
         }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c3a4930..c57243d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1296,6 +1296,22 @@
     public static final String ACTION_LOCKSCREEN_SETTINGS = "android.settings.LOCK_SCREEN_SETTINGS";
 
     /**
+     * Activity Action: Show settings of notifications on lockscreen.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_LOCKSCREEN_NOTIFICATIONS_SETTINGS =
+            "android.settings.LOCK_SCREEN_NOTIFICATIONS_SETTINGS";
+
+    /**
      * Activity Action: Show settings to allow pairing bluetooth devices.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -5707,6 +5723,7 @@
          * The value 1 - enable, 0 - disable
          * @hide
          */
+        @Readable
         public static final String NOTIFICATION_COOLDOWN_ENABLED =
             "notification_cooldown_enabled";
 
@@ -6335,6 +6352,16 @@
                 "mouse_swap_primary_button";
 
         /**
+         * Whether to enable mouse scrolling acceleration.
+         *
+         * When enabled, mouse scrolling is accelerated based on the user's scrolling speed.
+         * When disabled, mouse scrolling speed becomes directly proportional to the speed at which
+         * the wheel is turned.
+         * @hide
+         */
+        public static final String MOUSE_SCROLLING_ACCELERATION = "mouse_scrolling_acceleration";
+
+        /**
          * Pointer fill style, specified by
          * {@link android.view.PointerIcon.PointerIconVectorStyleFill} constants.
          *
@@ -6584,6 +6611,7 @@
             PRIVATE_SETTINGS.add(MOUSE_REVERSE_VERTICAL_SCROLLING);
             PRIVATE_SETTINGS.add(MOUSE_SWAP_PRIMARY_BUTTON);
             PRIVATE_SETTINGS.add(PREFERRED_REGION);
+            PRIVATE_SETTINGS.add(MOUSE_SCROLLING_ACCELERATION);
         }
 
         /**
diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java b/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java
index a086bf7..d476d96 100644
--- a/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java
+++ b/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java
@@ -30,26 +30,25 @@
 @FlaggedApi(Flags.FLAG_AAPM_API)
 @SystemApi
 public final class AdvancedProtectionFeature implements Parcelable {
-    private final String mId;
+    private final int mId;
 
     /**
      * Create an object identifying an Advanced Protection feature for AdvancedProtectionManager
-     * @param id A unique ID to identify this feature. It is used by Settings screens to display
-     *           information about this feature.
+     * @param id Feature identifier. It is used by Settings screens to display information about
+     *           this feature.
      */
-    public AdvancedProtectionFeature(@NonNull String id) {
+    public AdvancedProtectionFeature(@AdvancedProtectionManager.FeatureId int id) {
         mId = id;
     }
 
     private AdvancedProtectionFeature(Parcel in) {
-        mId = in.readString8();
+        mId = in.readInt();
     }
 
     /**
      * @return the unique ID representing this feature
      */
-    @NonNull
-    public String getId() {
+    public int getId() {
         return mId;
     }
 
@@ -60,7 +59,7 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString8(mId);
+        dest.writeInt(mId);
     }
 
     @NonNull
diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
index 59628e8..ea01fc9 100644
--- a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
+++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java
@@ -24,17 +24,18 @@
 import android.Manifest;
 import android.annotation.CallbackExecutor;
 import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.StringDef;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
+import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.RemoteException;
+import android.os.UserManager;
 import android.security.Flags;
 import android.util.Log;
 
@@ -59,54 +60,57 @@
     private static final String TAG = "AdvancedProtectionMgr";
 
     /**
-     * Advanced Protection's identifier for setting policies or restrictions in DevicePolicyManager.
+     * Advanced Protection's identifier for setting policies or restrictions in
+     * {@link DevicePolicyManager}.
      *
      * @hide */
     public static final String ADVANCED_PROTECTION_SYSTEM_ENTITY =
             "android.security.advancedprotection";
 
     /**
-     * Feature identifier for disallowing 2G.
+     * Feature identifier for disallowing connections to 2G networks.
      *
+     * @see UserManager#DISALLOW_CELLULAR_2G
      * @hide */
     @SystemApi
-    public static final String FEATURE_ID_DISALLOW_CELLULAR_2G =
-            "android.security.advancedprotection.feature_disallow_2g";
+    public static final int FEATURE_ID_DISALLOW_CELLULAR_2G = 0;
 
     /**
-     * Feature identifier for disallowing install of unknown sources.
+     * Feature identifier for disallowing installs of apps from unknown sources.
      *
+     * @see UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
      * @hide */
     @SystemApi
-    public static final String FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES =
-            "android.security.advancedprotection.feature_disallow_install_unknown_sources";
+    public static final int FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = 1;
 
     /**
-     * Feature identifier for disallowing USB.
+     * Feature identifier for disallowing USB connections.
      *
      * @hide */
     @SystemApi
-    public static final String FEATURE_ID_DISALLOW_USB =
-            "android.security.advancedprotection.feature_disallow_usb";
+    public static final int FEATURE_ID_DISALLOW_USB = 2;
 
     /**
-     * Feature identifier for disallowing WEP.
+     * Feature identifier for disallowing connections to Wi-Fi Wired Equivalent Privacy (WEP)
+     * networks.
      *
+     * @see WifiManager#isWepSupported()
      * @hide */
     @SystemApi
-    public static final String FEATURE_ID_DISALLOW_WEP =
-            "android.security.advancedprotection.feature_disallow_wep";
+    public static final int FEATURE_ID_DISALLOW_WEP = 3;
 
     /**
-     * Feature identifier for enabling MTE.
+     * Feature identifier for enabling the Memory Tagging Extension (MTE). MTE is a CPU extension
+     * that allows to protect against certain classes of security problems at a small runtime
+     * performance cost overhead.
      *
+     * @see DevicePolicyManager#setMtePolicy(int)
      * @hide */
     @SystemApi
-    public static final String FEATURE_ID_ENABLE_MTE =
-            "android.security.advancedprotection.feature_enable_mte";
+    public static final int FEATURE_ID_ENABLE_MTE = 4;
 
     /** @hide */
-    @StringDef(prefix = { "FEATURE_ID_" }, value = {
+    @IntDef(prefix = { "FEATURE_ID_" }, value = {
             FEATURE_ID_DISALLOW_CELLULAR_2G,
             FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES,
             FEATURE_ID_DISALLOW_USB,
@@ -116,7 +120,7 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface FeatureId {}
 
-    private static final Set<String> ALL_FEATURE_IDS = Set.of(
+    private static final Set<Integer> ALL_FEATURE_IDS = Set.of(
             FEATURE_ID_DISALLOW_CELLULAR_2G,
             FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES,
             FEATURE_ID_DISALLOW_USB,
@@ -135,9 +139,6 @@
      * Output: Nothing.
      *
      * @hide */
-    @SystemApi
-    @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION)
-    @FlaggedApi(android.security.Flags.FLAG_AAPM_API)
     public static final String ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG =
             "android.security.advancedprotection.action.SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG";
 
@@ -147,7 +148,6 @@
      *
      * @hide */
     @FeatureId
-    @SystemApi
     public static final String EXTRA_SUPPORT_DIALOG_FEATURE =
             "android.security.advancedprotection.extra.SUPPORT_DIALOG_FEATURE";
 
@@ -157,37 +157,41 @@
      *
      * @hide */
     @SupportDialogType
-    @SystemApi
     public static final String EXTRA_SUPPORT_DIALOG_TYPE =
             "android.security.advancedprotection.extra.SUPPORT_DIALOG_TYPE";
 
     /**
+     * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating an unknown action was blocked by
+     * advanced protection, hence the support dialog should display a default explanation.
+     *
+     * @hide */
+    public static final int SUPPORT_DIALOG_TYPE_UNKNOWN = 0;
+
+    /**
      * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user performed an action that was
      * blocked by advanced protection.
      *
      * @hide */
-    @SystemApi
-    public static final String SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION =
-            "android.security.advancedprotection.type_blocked_interaction";
+    public static final int SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION = 1;
 
     /**
      * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user pressed on a setting toggle
      * that was disabled by advanced protection.
      *
      * @hide */
-    @SystemApi
-    public static final String SUPPORT_DIALOG_TYPE_DISABLED_SETTING =
-            "android.security.advancedprotection.type_disabled_setting";
+    public static final int SUPPORT_DIALOG_TYPE_DISABLED_SETTING = 2;
 
     /** @hide */
-    @StringDef(prefix = { "SUPPORT_DIALOG_TYPE_" }, value = {
+    @IntDef(prefix = { "SUPPORT_DIALOG_TYPE_" }, value = {
+            SUPPORT_DIALOG_TYPE_UNKNOWN,
             SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION,
             SUPPORT_DIALOG_TYPE_DISABLED_SETTING,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SupportDialogType {}
 
-    private static final Set<String> ALL_SUPPORT_DIALOG_TYPES = Set.of(
+    private static final Set<Integer> ALL_SUPPORT_DIALOG_TYPES = Set.of(
+            SUPPORT_DIALOG_TYPE_UNKNOWN,
             SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION,
             SUPPORT_DIALOG_TYPE_DISABLED_SETTING);
 
@@ -324,15 +328,13 @@
      *                disabled by advanced protection.
      * @hide
      */
-    @SystemApi
-    public @NonNull Intent createSupportIntent(@NonNull @FeatureId String featureId,
-            @Nullable @SupportDialogType String type) {
-        Objects.requireNonNull(featureId);
+    public static @NonNull Intent createSupportIntent(@FeatureId int featureId,
+            @SupportDialogType int type) {
         if (!ALL_FEATURE_IDS.contains(featureId)) {
             throw new IllegalArgumentException(featureId + " is not a valid feature ID. See"
                     + " FEATURE_ID_* APIs.");
         }
-        if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) {
+        if (!ALL_SUPPORT_DIALOG_TYPES.contains(type)) {
             throw new IllegalArgumentException(type + " is not a valid type. See"
                     + " SUPPORT_DIALOG_TYPE_* APIs.");
         }
@@ -340,21 +342,19 @@
         Intent intent = new Intent(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG);
         intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
         intent.putExtra(EXTRA_SUPPORT_DIALOG_FEATURE, featureId);
-        if (type != null) {
-            intent.putExtra(EXTRA_SUPPORT_DIALOG_TYPE, type);
-        }
+        intent.putExtra(EXTRA_SUPPORT_DIALOG_TYPE, type);
         return intent;
     }
 
     /** @hide */
-    public @NonNull Intent createSupportIntentForPolicyIdentifierOrRestriction(
-            @NonNull String identifier, @Nullable @SupportDialogType String type) {
+    public static @NonNull Intent createSupportIntentForPolicyIdentifierOrRestriction(
+            @NonNull String identifier, @SupportDialogType int type) {
         Objects.requireNonNull(identifier);
-        if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) {
+        if (!ALL_SUPPORT_DIALOG_TYPES.contains(type)) {
             throw new IllegalArgumentException(type + " is not a valid type. See"
                     + " SUPPORT_DIALOG_TYPE_* APIs.");
         }
-        final String featureId;
+        final int featureId;
         if (DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY.equals(identifier)) {
             featureId = FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES;
         } else if (DISALLOW_CELLULAR_2G.equals(identifier)) {
diff --git a/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java b/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java
index b479ca7..76ee448 100644
--- a/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java
+++ b/core/java/android/security/intrusiondetection/IntrusionDetectionEvent.java
@@ -91,12 +91,12 @@
             };
 
     /**
-     * Creates an IntrusionDetectionEvent object with a
-     * {@link SecurityEvent} object as the event source.
+     * Creates an IntrusionDetectionEvent object with a {@link SecurityEvent} object as the event
+     * source.
      *
      * @param securityEvent The SecurityEvent object.
      */
-    public IntrusionDetectionEvent(@NonNull SecurityEvent securityEvent) {
+    private IntrusionDetectionEvent(@NonNull SecurityEvent securityEvent) {
         mType = SECURITY_EVENT;
         mSecurityEvent = securityEvent;
         mNetworkEventDns = null;
@@ -104,12 +104,11 @@
     }
 
     /**
-     * Creates an IntrusionDetectionEvent object with a
-     * {@link DnsEvent} object as the event source.
+     * Creates an IntrusionDetectionEvent object with a {@link DnsEvent} object as the event source.
      *
      * @param dnsEvent The DnsEvent object.
      */
-    public IntrusionDetectionEvent(@NonNull DnsEvent dnsEvent) {
+    private IntrusionDetectionEvent(@NonNull DnsEvent dnsEvent) {
         mType = NETWORK_EVENT_DNS;
         mNetworkEventDns = dnsEvent;
         mSecurityEvent = null;
@@ -117,18 +116,52 @@
     }
 
     /**
-     * Creates an IntrusionDetectionEvent object with a
-     * {@link ConnectEvent} object as the event source.
+     * Creates an IntrusionDetectionEvent object with a {@link ConnectEvent} object as the event
+     * source.
      *
      * @param connectEvent The ConnectEvent object.
      */
-    public IntrusionDetectionEvent(@NonNull ConnectEvent connectEvent) {
+    private IntrusionDetectionEvent(@NonNull ConnectEvent connectEvent) {
         mType = NETWORK_EVENT_CONNECT;
         mNetworkEventConnect = connectEvent;
         mSecurityEvent = null;
         mNetworkEventDns = null;
     }
 
+    /**
+     * Creates an IntrusionDetectionEvent object with a {@link SecurityEvent} object as the event
+     * source.
+     *
+     * @param securityEvent The SecurityEvent object.
+     */
+    @NonNull
+    public static IntrusionDetectionEvent createForSecurityEvent(
+            @NonNull SecurityEvent securityEvent) {
+        return new IntrusionDetectionEvent(securityEvent);
+    }
+
+    /**
+     * Creates an IntrusionDetectionEvent object with a {@link DnsEvent} object as the event source.
+     *
+     * @param dnsEvent The DnsEvent object.
+     */
+    @NonNull
+    public static IntrusionDetectionEvent createForDnsEvent(@NonNull DnsEvent dnsEvent) {
+        return new IntrusionDetectionEvent(dnsEvent);
+    }
+
+    /**
+     * Creates an IntrusionDetectionEvent object with a {@link ConnectEvent} object as the event
+     * source.
+     *
+     * @param connectEvent The ConnectEvent object.
+     */
+    @NonNull
+    public static IntrusionDetectionEvent createForConnectEvent(
+            @NonNull ConnectEvent connectEvent) {
+        return new IntrusionDetectionEvent(connectEvent);
+    }
+
     private IntrusionDetectionEvent(@NonNull Parcel in) {
         mType = in.readInt();
         switch (mType) {
diff --git a/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java b/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java
index 2e2d0f7..4755eaf 100644
--- a/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java
+++ b/core/java/android/security/intrusiondetection/IntrusionDetectionEventTransport.java
@@ -44,7 +44,8 @@
  * which will then be delivered to the specified location.
  *
  * Usage:
- * 1. Obtain an instance of {@link IntrusionDetectionEventTransport} using the constructor.
+ * 1. Obtain an instance of {@link IntrusionDetectionEventTransport} using the appropriate
+ *    creation method.
  * 2. Initialize the transport by calling {@link #initialize()}.
  * 3. Add events to the transport queue using {@link #addData(List)}.
  * 4. Release the transport when finished by calling {@link #release()}.
diff --git a/core/java/android/security/intrusiondetection/IntrusionDetectionManager.java b/core/java/android/security/intrusiondetection/IntrusionDetectionManager.java
index e246338..8a7ec0d 100644
--- a/core/java/android/security/intrusiondetection/IntrusionDetectionManager.java
+++ b/core/java/android/security/intrusiondetection/IntrusionDetectionManager.java
@@ -230,7 +230,7 @@
     /**
      * Disable intrusion detection.
      * If successful, IntrusionDetectionService will transition to {@link #STATE_DISABLED}.
-     * <p>
+     *
      * When intrusion detection is disabled, device events will no longer be collected.
      * Any events that have been collected but not yet sent to IntrusionDetectionEventTransport
      * will be transferred as a final batch.
diff --git a/core/java/android/security/net/config/NetworkSecurityTrustManager.java b/core/java/android/security/net/config/NetworkSecurityTrustManager.java
index d9cc82a..029b674 100644
--- a/core/java/android/security/net/config/NetworkSecurityTrustManager.java
+++ b/core/java/android/security/net/config/NetworkSecurityTrustManager.java
@@ -16,16 +16,17 @@
 
 package android.security.net.config;
 
+import android.util.ArrayMap;
+
 import com.android.org.conscrypt.TrustManagerImpl;
 
-import android.util.ArrayMap;
 import java.io.IOException;
 import java.net.Socket;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
 import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 import java.security.MessageDigest;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -105,7 +106,7 @@
 
     /**
      * Hostname aware version of {@link #checkServerTrusted(X509Certificate[], String)}.
-     * This interface is used by conscrypt and android.net.http.X509TrustManagerExtensions do not
+     * This interface is used by Conscrypt and android.net.http.X509TrustManagerExtensions do not
      * modify without modifying those callers.
      */
     public List<X509Certificate> checkServerTrusted(X509Certificate[] certs, String authType,
@@ -115,6 +116,19 @@
         return trustedChain;
     }
 
+    /**
+     * This interface is used by Conscrypt and android.net.http.X509TrustManagerExtensions do not
+     * modify without modifying those callers.
+     */
+    public List<X509Certificate> checkServerTrusted(X509Certificate[] certs,
+            byte[] ocspData, byte[] tlsSctData, String authType,
+            String host) throws CertificateException {
+        List<X509Certificate> trustedChain = mDelegate.checkServerTrusted(
+                certs, ocspData, tlsSctData, authType, host);
+        checkPins(trustedChain);
+        return trustedChain;
+    }
+
     private void checkPins(List<X509Certificate> chain) throws CertificateException {
         PinSet pinSet = mNetworkSecurityConfig.getPins();
         if (pinSet.pins.isEmpty()
diff --git a/core/java/android/security/net/config/OWNERS b/core/java/android/security/net/config/OWNERS
index 85ce3c6..e945ff9 100644
--- a/core/java/android/security/net/config/OWNERS
+++ b/core/java/android/security/net/config/OWNERS
@@ -1,5 +1,6 @@
-# Bug component: 36824
-set noparent
+# Bug component: 1479456
 
-cbrubaker@google.com
+bessiej@google.com
 brambonne@google.com
+sandrom@google.com
+tweek@google.com
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index 58dc4ba..a1bdec5 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -120,7 +120,7 @@
 
     /**
      * Hostname aware version of {@link #checkServerTrusted(X509Certificate[], String)}.
-     * This interface is used by conscrypt and android.net.http.X509TrustManagerExtensions do not
+     * This interface is used by Conscrypt and android.net.http.X509TrustManagerExtensions do not
      * modify without modifying those callers.
      */
     @UnsupportedAppUsage
@@ -134,6 +134,22 @@
         return config.getTrustManager().checkServerTrusted(certs, authType, hostname);
     }
 
+    /**
+     * This interface is used by Conscrypt and android.net.http.X509TrustManagerExtensions do not
+     * modify without modifying those callers.
+     */
+    public List<X509Certificate> checkServerTrusted(X509Certificate[] certs,
+            byte[] ocspData, byte[] tlsSctData, String authType,
+            String hostname) throws CertificateException {
+        if (hostname == null && mConfig.hasPerDomainConfigs()) {
+            throw new CertificateException(
+                    "Domain specific configurations require that the hostname be provided");
+        }
+        NetworkSecurityConfig config = mConfig.getConfigForHostname(hostname);
+        return config.getTrustManager().checkServerTrusted(
+                certs, ocspData, tlsSctData, authType, hostname);
+    }
+
     @Override
     public X509Certificate[] getAcceptedIssuers() {
         // getAcceptedIssuers is meant to be used to determine which trust anchors the server will
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
index 90136ae..ffe8086 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
@@ -93,6 +93,10 @@
  * must do its own state management (keeping in mind that the service's process might be killed
  * by the Android System when unbound; for example, if the device is running low in memory).
  *
+ * <p> The service also provides pending intents to override the system's Quick Access activities
+ * via the {@link #getTargetActivityPendingIntent} and the
+ * {@link #getGestureTargetActivityPendingIntent} method.
+ *
  * <p>
  * <a name="ErrorHandling"></a>
  * <h3>Error handling</h3>
@@ -384,6 +388,10 @@
      *
      * <p>The pending intent will be sent when the user performs a gesture to open Wallet.
      * The pending intent should launch an activity.
+     *
+     * <p> If the gesture is performed and this method returns null, the system will launch the
+     * activity specified by the {@link #getTargetActivityPendingIntent} method. If that method
+     * also returns null, the system will launch the system-provided card switcher activity.
      */
     @Nullable
     @FlaggedApi(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP)
diff --git a/core/java/android/service/settings/preferences/GetValueRequest.java b/core/java/android/service/settings/preferences/GetValueRequest.java
index 4f82800..db5c57c 100644
--- a/core/java/android/service/settings/preferences/GetValueRequest.java
+++ b/core/java/android/service/settings/preferences/GetValueRequest.java
@@ -108,6 +108,7 @@
     /**
      * Builder to construct {@link GetValueRequest}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         private final String mScreenKey;
         private final String mPreferenceKey;
diff --git a/core/java/android/service/settings/preferences/GetValueResult.java b/core/java/android/service/settings/preferences/GetValueResult.java
index 369dea7..7911315 100644
--- a/core/java/android/service/settings/preferences/GetValueResult.java
+++ b/core/java/android/service/settings/preferences/GetValueResult.java
@@ -170,6 +170,7 @@
     /**
      * Builder to construct {@link GetValueResult}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         @ResultCode
         private final int mResultCode;
diff --git a/core/java/android/service/settings/preferences/MetadataRequest.java b/core/java/android/service/settings/preferences/MetadataRequest.java
index ffecc6b..e041715 100644
--- a/core/java/android/service/settings/preferences/MetadataRequest.java
+++ b/core/java/android/service/settings/preferences/MetadataRequest.java
@@ -65,6 +65,7 @@
     /**
      * Builder to construct {@link MetadataRequest}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         /** Constructs an immutable {@link MetadataRequest} object. */
         @NonNull
diff --git a/core/java/android/service/settings/preferences/MetadataResult.java b/core/java/android/service/settings/preferences/MetadataResult.java
index 6a65dcc..e62fa8f 100644
--- a/core/java/android/service/settings/preferences/MetadataResult.java
+++ b/core/java/android/service/settings/preferences/MetadataResult.java
@@ -131,6 +131,7 @@
     /**
      * Builder to construct {@link MetadataResult}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         @ResultCode
         private final int mResultCode;
diff --git a/core/java/android/service/settings/preferences/SetValueRequest.java b/core/java/android/service/settings/preferences/SetValueRequest.java
index f7600ae..77581d9 100644
--- a/core/java/android/service/settings/preferences/SetValueRequest.java
+++ b/core/java/android/service/settings/preferences/SetValueRequest.java
@@ -123,6 +123,7 @@
     /**
      * Builder to construct {@link SetValueRequest}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         private final String mScreenKey;
         private final String mPreferenceKey;
diff --git a/core/java/android/service/settings/preferences/SetValueResult.java b/core/java/android/service/settings/preferences/SetValueResult.java
index cb1776a..513f7a7 100644
--- a/core/java/android/service/settings/preferences/SetValueResult.java
+++ b/core/java/android/service/settings/preferences/SetValueResult.java
@@ -156,6 +156,7 @@
     /**
      * Builder to construct {@link SetValueResult}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         @ResultCode
         private final int mResultCode;
diff --git a/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java b/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java
index ea7d4a6..30631f2 100644
--- a/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java
+++ b/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java
@@ -102,6 +102,7 @@
     /**
      * Returns the breadcrumbs (navigation context) of Preference.
      * <p>May be empty.
+     * @hide restrict to platform; may be opened wider in the future
      */
     @NonNull
     public List<String> getBreadcrumbs() {
@@ -189,33 +190,32 @@
     @IntDef(value = {
             NO_SENSITIVITY,
             EXPECT_POST_CONFIRMATION,
-            EXPECT_PRE_CONFIRMATION,
+            DEEPLINK_ONLY,
             NO_DIRECT_ACCESS,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface WriteSensitivity {}
 
     /**
-     * Indicates preference is not sensitive.
+     * Indicates preference is not write-sensitive.
      * <p>Its value is writable without explicit consent, assuming all necessary permissions are
      * granted.
      */
     public static final int NO_SENSITIVITY = 0;
     /**
-     * Indicates preference is mildly sensitive.
+     * Indicates preference is mildly write-sensitive.
      * <p>In addition to necessary permissions, after writing its value the user should be
      * given the option to revert back.
      */
     public static final int EXPECT_POST_CONFIRMATION = 1;
     /**
-     * Indicates preference is sensitive.
-     * <p>In addition to necessary permissions, the user should be prompted for confirmation prior
-     * to making a change. Otherwise it is suggested to provide a deeplink to the Preference's page
-     * instead, accessible via {@link #getLaunchIntent}.
+     * Indicates preference is write-sensitive.
+     * <p>This preference cannot be changed through this API; instead a deeplink to the Preference's
+     * page should be used instead, accessible via {@link #getLaunchIntent}.
      */
-    public static final int EXPECT_PRE_CONFIRMATION = 2;
+    public static final int DEEPLINK_ONLY = 2;
     /**
-     * Indicates preference is highly sensitivity and carries significant user-risk.
+     * Indicates preference is highly write-sensitivity and carries significant user-risk.
      * <p>This Preference cannot be changed through this API and no direct deeplink is available.
      * Other Metadata is still available.
      */
@@ -303,6 +303,7 @@
     /**
      * Builder to construct {@link SettingsPreferenceMetadata}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         private final String mScreenKey;
         private final String mKey;
@@ -355,6 +356,7 @@
 
         /**
          * Sets the preference breadcrumbs (navigation context).
+         * @hide
          */
         @NonNull
         public Builder setBreadcrumbs(@NonNull List<String> breadcrumbs) {
diff --git a/core/java/android/service/settings/preferences/SettingsPreferenceValue.java b/core/java/android/service/settings/preferences/SettingsPreferenceValue.java
index 08826ca..eea93b3 100644
--- a/core/java/android/service/settings/preferences/SettingsPreferenceValue.java
+++ b/core/java/android/service/settings/preferences/SettingsPreferenceValue.java
@@ -170,6 +170,7 @@
     /**
      * Builder to construct {@link SettingsPreferenceValue}.
      */
+    @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
     public static final class Builder {
         @Type
         private final int mType;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 2061aba..990b099 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -2409,6 +2409,12 @@
                 };
 
         private Surface getOrCreateBLASTSurface(int width, int height, int format) {
+            if (mBbqSurfaceControl == null || !mBbqSurfaceControl.isValid()) {
+                Log.w(TAG, "Skipping BlastBufferQueue update/create"
+                    + " - invalid surface control");
+                return null;
+            }
+
             Surface ret = null;
             if (mBlastBufferQueue == null) {
                 mBlastBufferQueue = new BLASTBufferQueue("Wallpaper", mBbqSurfaceControl,
@@ -2418,11 +2424,7 @@
                 // it hasn't changed and there is no need to update.
                 ret = mBlastBufferQueue.createSurface();
             } else {
-                if (mBbqSurfaceControl != null && mBbqSurfaceControl.isValid()) {
-                    mBlastBufferQueue.update(mBbqSurfaceControl, width, height, format);
-                } else {
-                    Log.w(TAG, "Skipping BlastBufferQueue update - invalid surface control");
-                }
+                mBlastBufferQueue.update(mBbqSurfaceControl, width, height, format);
             }
 
             return ret;
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index fb1bd17..6116d59 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -70,3 +70,11 @@
     is_fixed_read_only: true
     bug: "352538294"
 }
+
+flag {
+    name: "system_server_large_perfetto_shmem_buffer"
+    namespace: "windowing_tools"
+    description: "Large perfetto shmem buffer"
+    is_fixed_read_only: true
+    bug: "382369925"
+}
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 089b5c2..992790e 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.flags.Flags.bufferStuffingRecovery;
 import static android.view.flags.Flags.FLAG_EXPECTED_PRESENTATION_TIME_API;
 import static android.view.DisplayEventReceiver.VSYNC_SOURCE_APP;
 import static android.view.DisplayEventReceiver.VSYNC_SOURCE_SURFACE_FLINGER;
@@ -239,6 +240,7 @@
          * stuffing events.
          */
         public void reset() {
+            isStuffed.set(false);
             isRecovering = false;
             numberWaitsForNextVsync = 0;
         }
@@ -965,22 +967,24 @@
 
         // Evaluate if buffer stuffing recovery needs to start or end, and
         // what actions need to be taken for recovery.
-        switch (updateBufferStuffingState(frameTimeNanos, vsyncEventData)) {
-            case NONE:
-                // Without buffer stuffing recovery, offsetFrameTimeNanos is
-                // synonymous with frameTimeNanos.
-                break;
-            case OFFSET:
-                // Add animation offset. Used to update frame timeline with
-                // offset before jitter is calculated.
-                offsetFrameTimeNanos = frameTimeNanos - frameIntervalNanos;
-                break;
-            case DELAY_FRAME:
-                // Intentional frame delay to help reduce queued buffer count.
-                scheduleVsyncLocked();
-                return;
-            default:
-                break;
+        if (bufferStuffingRecovery()) {
+            switch (updateBufferStuffingState(frameTimeNanos, vsyncEventData)) {
+                case NONE:
+                    // Without buffer stuffing recovery, offsetFrameTimeNanos is
+                    // synonymous with frameTimeNanos.
+                    break;
+                case OFFSET:
+                    // Add animation offset. Used to update frame timeline with
+                    // offset before jitter is calculated.
+                    offsetFrameTimeNanos = frameTimeNanos - frameIntervalNanos;
+                    break;
+                case DELAY_FRAME:
+                    // Intentional frame delay to help reduce queued buffer count.
+                    scheduleVsyncLocked();
+                    return;
+                default:
+                    break;
+            }
         }
 
         try {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0c8a0d6..ca0959a 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1597,7 +1597,9 @@
             // Although we only care about the HDR/SDR ratio changing, that can also come in the
             // form of the larger DISPLAY_CHANGED event
             mGlobal.registerDisplayListener(toRegister, executor,
-                    DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+                    DisplayManagerGlobal
+                                    .INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
                             | DisplayManagerGlobal
                                     .INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
                     ActivityThread.currentPackageName());
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index ba098eb5..e75b1b0 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -447,7 +447,18 @@
     }
 
     public boolean equals(DisplayInfo other) {
-        return other != null
+        return equals(other, /* compareRefreshRate */ true);
+    }
+
+    /**
+     * Compares if the two DisplayInfo objects are equal or not
+     * @param other The other DisplayInfo against which the comparison is to be done
+     * @param compareRefreshRate Indicates if the refresh rate is also to be considered in
+     *                           comparison
+     * @return
+     */
+    public boolean equals(DisplayInfo other, boolean compareRefreshRate) {
+        boolean isEqualWithoutRefreshRate =  other != null
                 && layerStack == other.layerStack
                 && flags == other.flags
                 && type == other.type
@@ -466,7 +477,6 @@
                 && logicalHeight == other.logicalHeight
                 && Objects.equals(displayCutout, other.displayCutout)
                 && rotation == other.rotation
-                && modeId == other.modeId
                 && hasArrSupport == other.hasArrSupport
                 && Objects.equals(frameRateCategoryRate, other.frameRateCategoryRate)
                 && Arrays.equals(supportedRefreshRates, other.supportedRefreshRates)
@@ -490,7 +500,6 @@
                 && ownerUid == other.ownerUid
                 && Objects.equals(ownerPackageName, other.ownerPackageName)
                 && removeMode == other.removeMode
-                && getRefreshRate() == other.getRefreshRate()
                 && brightnessMinimum == other.brightnessMinimum
                 && brightnessMaximum == other.brightnessMaximum
                 && brightnessDefault == other.brightnessDefault
@@ -504,6 +513,13 @@
                 && Objects.equals(
                 thermalBrightnessThrottlingDataId, other.thermalBrightnessThrottlingDataId)
                 && canHostTasks == other.canHostTasks;
+
+        if (compareRefreshRate) {
+            return isEqualWithoutRefreshRate
+                    && (getRefreshRate() == other.getRefreshRate())
+                    && (modeId == other.modeId);
+        }
+        return isEqualWithoutRefreshRate;
     }
 
     @Override
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 072a037..2b40874 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -722,6 +722,9 @@
      */
     void setDisplayImePolicy(int displayId, int imePolicy);
 
+    /** Called when the expanded state of notification shade is changed. */
+    void onNotificationShadeExpanded(IBinder token, boolean expanded);
+
     /**
      * Waits until input information has been sent from WindowManager to native InputManager,
      * optionally waiting for animations to complete.
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index a8d4e2d..48dfdd4 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,6 +16,9 @@
 
 package android.view;
 
+
+import static com.android.hardware.input.Flags.removeFallbackModifiers;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -458,7 +461,15 @@
         FallbackAction action = FallbackAction.obtain();
         metaState = KeyEvent.normalizeMetaState(metaState);
         if (nativeGetFallbackAction(mPtr, keyCode, metaState, action)) {
-            action.metaState = KeyEvent.normalizeMetaState(action.metaState);
+            if (removeFallbackModifiers()) {
+                // Strip all modifiers. This is safe to do since only exact keyCode + metaState
+                // modifiers will trigger a fallback.
+                // E.g. Ctrl + Space -> language_switch (fallback generated)
+                //      Ctrl + Alt + Space -> Ctrl + Alt + Space (no fallback generated)
+                action.metaState = 0;
+            } else {
+                action.metaState = KeyEvent.normalizeMetaState(action.metaState);
+            }
             return action;
         }
         action.recycle();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 38e4e27..ad43c7b 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2590,6 +2590,32 @@
         return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
     }
 
+    /**
+     * Returns whether the key code passed as argument is allowed for visible background users.
+     * Visible background users are expected to run on secondary displays with certain limitations
+     * on system keys.
+     *
+     * @hide
+     */
+    public static boolean isVisibleBackgroundUserAllowedKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_POWER:
+            case KeyEvent.KEYCODE_SLEEP:
+            case KeyEvent.KEYCODE_WAKEUP:
+            case KeyEvent.KEYCODE_CALL:
+            case KeyEvent.KEYCODE_ENDCALL:
+            case KeyEvent.KEYCODE_ASSIST:
+            case KeyEvent.KEYCODE_VOICE_ASSIST:
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+            case KeyEvent.KEYCODE_RECENT_APPS:
+            case KeyEvent.KEYCODE_APP_SWITCH:
+            case KeyEvent.KEYCODE_NOTIFICATION:
+                return false;
+        }
+        return true;
+    }
+
     /** {@inheritDoc} */
     @Override
     public final int getDeviceId() {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6e6e87b..4fc1cfc 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -206,7 +206,8 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"FRAME_RATE_COMPATIBILITY_"},
             value = {FRAME_RATE_COMPATIBILITY_DEFAULT, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
-                    FRAME_RATE_COMPATIBILITY_GTE})
+                    FRAME_RATE_COMPATIBILITY_AT_LEAST, FRAME_RATE_COMPATIBILITY_EXACT,
+                    FRAME_RATE_COMPATIBILITY_MIN})
     public @interface FrameRateCompatibility {}
 
     // From native_window.h. Keep these in sync.
@@ -219,7 +220,7 @@
      * In Android version {@link Build.VERSION_CODES#BAKLAVA} and above, use
      * {@link FRAME_RATE_COMPATIBILITY_DEFAULT} for game content.
      * For other cases, see {@link FRAME_RATE_COMPATIBILITY_FIXED_SOURCE} and
-     * {@link FRAME_RATE_COMPATIBILITY_GTE}.
+     * {@link FRAME_RATE_COMPATIBILITY_AT_LEAST}.
      */
     public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0;
 
@@ -234,7 +235,7 @@
     public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1;
 
     /**
-     * The surface requests a frame rate that is greater than or equal to the specified frame rate.
+     * The surface requests a frame rate that is at least the specified frame rate.
      * This value should be used for UIs, animations, scrolling and fling, and anything that is not
      * a game or video.
      *
@@ -242,7 +243,7 @@
      * {@link FRAME_RATE_COMPATIBILITY_DEFAULT}.
      */
     @FlaggedApi(com.android.graphics.surfaceflinger.flags.Flags.FLAG_ARR_SETFRAMERATE_GTE_ENUM)
-    public static final int FRAME_RATE_COMPATIBILITY_GTE = 2;
+    public static final int FRAME_RATE_COMPATIBILITY_AT_LEAST = 2;
 
     /**
      * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index f22505b..833f2d9 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -22,7 +22,6 @@
 import static android.graphics.Matrix.MSKEW_Y;
 import static android.graphics.Matrix.MTRANS_X;
 import static android.graphics.Matrix.MTRANS_Y;
-import static android.view.flags.Flags.bufferStuffingRecovery;
 import static android.view.SurfaceControlProto.HASH_CODE;
 import static android.view.SurfaceControlProto.LAYER_ID;
 import static android.view.SurfaceControlProto.NAME;
@@ -5118,11 +5117,9 @@
          */
         @NonNull
         public Transaction setRecoverableFromBufferStuffing(@NonNull SurfaceControl sc) {
-            if (bufferStuffingRecovery()) {
-                checkPreconditions(sc);
-                nativeSetFlags(mNativeObject, sc.mNativeObject, RECOVERABLE_FROM_BUFFER_STUFFING,
-                        RECOVERABLE_FROM_BUFFER_STUFFING);
-            }
+            checkPreconditions(sc);
+            nativeSetFlags(mNativeObject, sc.mNativeObject, RECOVERABLE_FROM_BUFFER_STUFFING,
+                    RECOVERABLE_FROM_BUFFER_STUFFING);
             return this;
         }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d13f0e2..d88b6d6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -27,7 +27,7 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
-import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
+import static android.view.Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 import static android.view.accessibility.Flags.FLAG_DEPRECATE_ACCESSIBILITY_ANNOUNCEMENT_APIS;
@@ -34199,7 +34199,8 @@
                 && viewRootImpl.shouldCheckFrameRateCategory()
                 && parent instanceof View
                 && ((View) parent).getFrameContentVelocity() <= 0
-                && !isInputMethodWindowType) {
+                && !isInputMethodWindowType
+                && viewRootImpl.getFrameRateCompatibility() != FRAME_RATE_COMPATIBILITY_AT_LEAST) {
 
             return FRAME_RATE_CATEGORY_HIGH_HINT | FRAME_RATE_CATEGORY_REASON_BOOST;
         }
@@ -34251,7 +34252,7 @@
                 compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
                 frameRateToSet = frameRate;
             } else {
-                compatibility = FRAME_RATE_COMPATIBILITY_GTE;
+                compatibility = FRAME_RATE_COMPATIBILITY_AT_LEAST;
                 frameRateToSet = velocityFrameRate;
             }
             viewRootImpl.votePreferredFrameRate(frameRateToSet, compatibility);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1d27574..16cdb64 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -38,7 +38,7 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
-import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
+import static android.view.Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_BOOST;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_CONFLICTED;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
@@ -1828,7 +1828,8 @@
                         | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_STATE
                         | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED
                 : DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-                        | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+                        | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                        | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
                         | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
         DisplayManagerGlobal
                 .getInstance()
@@ -13271,7 +13272,7 @@
      * We set category to HIGH if the maximum frame rate is greater than 60.
      * Otherwise, we set category to NORMAL.
      *
-     * Use FRAME_RATE_COMPATIBILITY_GTE for velocity and FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
+     * Use FRAME_RATE_COMPATIBILITY_AT_LEAST for velocity and FRAME_RATE_COMPATIBILITY_FIXED_SOURCE
      * for TextureView video play and user requested frame rate.
      *
      * @param frameRate the preferred frame rate of a View
@@ -13282,7 +13283,7 @@
         if (frameRate <= 0) {
             return;
         }
-        if (frameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE && !mIsPressedGesture) {
+        if (frameRateCompatibility == FRAME_RATE_COMPATIBILITY_AT_LEAST && !mIsPressedGesture) {
             mIsTouchBoosting = false;
             mIsFrameRateBoosting = false;
             if (!sToolkitFrameRateVelocityMappingReadOnlyFlagValue) {
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 70c899f..8baa55f 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -142,6 +142,11 @@
     }
 
     @Override
+    void internalNotifySessionFlushEvent(int sessionId) {
+        getMainCaptureSession().internalNotifySessionFlushEvent(sessionId);
+    }
+
+    @Override
     boolean isContentCaptureEnabled() {
         return getMainCaptureSession().isContentCaptureEnabled();
     }
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index db4ac5d..efd3916 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -18,7 +18,9 @@
 import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
 import static android.view.contentcapture.ContentCaptureManager.DEBUG;
 import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
+import static android.view.contentcapture.flags.Flags.FLAG_CCAPI_BAKLAVA_ENABLED;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -137,6 +139,12 @@
      */
     public static final int TYPE_WINDOW_BOUNDS_CHANGED = 10;
 
+    /**
+     * Called to flush a semantics meaningful view changes status to Intelligence Service.
+     */
+    @FlaggedApi(FLAG_CCAPI_BAKLAVA_ENABLED)
+    public static final int TYPE_SESSION_FLUSH = 11;
+
     /** @hide */
     @IntDef(prefix = { "TYPE_" }, value = {
             TYPE_VIEW_APPEARED,
@@ -149,6 +157,7 @@
             TYPE_SESSION_RESUMED,
             TYPE_VIEW_INSETS_CHANGED,
             TYPE_WINDOW_BOUNDS_CHANGED,
+            TYPE_SESSION_FLUSH,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType{}
@@ -697,6 +706,8 @@
                 return "VIEW_INSETS_CHANGED";
             case TYPE_WINDOW_BOUNDS_CHANGED:
                 return "TYPE_WINDOW_BOUNDS_CHANGED";
+            case TYPE_SESSION_FLUSH:
+                return "TYPE_SESSION_FLUSH";
             default:
                 return "UKNOWN_TYPE: " + type;
         }
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 0ca36ba2..9aeec20 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -19,8 +19,10 @@
 import static android.view.contentcapture.ContentCaptureHelper.sDebug;
 import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
 import static android.view.contentcapture.ContentCaptureManager.NO_SESSION_ID;
+import static android.view.contentcapture.flags.Flags.FLAG_CCAPI_BAKLAVA_ENABLED;
 
 import android.annotation.CallSuper;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -548,6 +550,35 @@
 
     abstract void internalNotifyViewInsetsChanged(int sessionId, @NonNull Insets viewInsets);
 
+    /**
+     * Flushes an internal buffer of UI events and signals System Intelligence (SI) that a
+     * semantically meaningful state has been reached. SI uses this signal to potentially
+     * rebuild the view hierarchy and understand the current state of the UI.
+     *
+     * <p>UI events are often batched together for performance reasons. A semantic batch
+     * represents a series of events that, when applied sequentially, result in a
+     * meaningful and complete UI state.
+     *
+     * <p>It is crucial to call {@code flush()} after completing a semantic batch to ensure
+     * SI can accurately reconstruct the view hierarchy.
+     *
+     * <p><b>Premature Flushing:</b> Calling {@code flush()} within a semantic batch may
+     * lead to SI failing to rebuild the view hierarchy correctly. This could manifest as
+     * incorrect ordering of sibling nodes.
+     *
+     * <p><b>Delayed Flushing:</b> While not immediately flushing after a semantic batch is
+     * generally safe, it's recommended to do so as soon as possible. In the worst-case
+     * scenario where a {@code flush()} is never called, SI will attempt to process the
+     * events after a short delay based on view appearance and disappearance events.
+     */
+    @FlaggedApi(FLAG_CCAPI_BAKLAVA_ENABLED)
+    public void flush() {
+        internalNotifySessionFlushEvent(mId);
+    }
+
+    /** @hide */
+    abstract void internalNotifySessionFlushEvent(int sessionId);
+
     /** @hide */
     public void notifyViewTreeEvent(boolean started) {
         internalNotifyViewTreeEvent(mId, started);
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index eb827dd..2fb78c0 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -17,6 +17,7 @@
 
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_CONTEXT_UPDATED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FLUSH;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_PAUSED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_RESUMED;
 import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
@@ -623,6 +624,8 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     @Override
     public void flush(@FlushReason int reason) {
+        // TODO: b/380381249 renaming the internal APIs to prevent confusions between this and the
+        // public API.
         runOnContentCaptureThread(() -> flushImpl(reason));
     }
 
@@ -890,6 +893,12 @@
         enqueueEvent(event);
     }
 
+    @Override
+    void internalNotifySessionFlushEvent(int sessionId) {
+        final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, TYPE_SESSION_FLUSH);
+        enqueueEvent(event, FORCE_FLUSH);
+    }
+
     private List<ContentCaptureEvent> clearBufferEvents() {
         final ArrayList<ContentCaptureEvent> bufferEvents = new ArrayList<>();
         ContentCaptureEvent event;
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 9ac273f..30f4cae 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 544200
 
-hackz@google.com
-shivanker@google.com
+dariofreni@google.com
+klikli@google.com
+shikhamalhotra@google.com
diff --git a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
index 416a877..f709ed7 100644
--- a/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
+++ b/core/java/android/view/contentcapture/flags/content_capture_flags.aconfig
@@ -7,3 +7,10 @@
     description: "Feature flag for running content capture tasks on background thread"
     bug: "309411951"
 }
+
+flag {
+    name: "ccapi_baklava_enabled"
+    namespace: "machine_learning"
+    description: "Feature flag for baklava content capture API"
+    bug: "380381249"
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index f82e5f9..d5f471e 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -938,27 +938,6 @@
             synchronized (mH) {
                 if (mCurRootView == viewRootImpl) {
                     mCurRootViewWindowFocused = false;
-
-                    if (Flags.refactorInsetsController() && mCurRootView != null) {
-                        final int softInputMode = mCurRootView.mWindowAttributes.softInputMode;
-                        final int state =
-                                softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
-                        if (state == WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) {
-                            // when losing focus (e.g., by going to another window), we reset the
-                            // requestedVisibleTypes of WindowInsetsController by hiding the IME
-                            final var statsToken = ImeTracker.forLogging().onStart(
-                                    ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT,
-                                    SoftInputShowHideReason.HIDE_WINDOW_LOST_FOCUS,
-                                    false /* fromUser */);
-                            if (DEBUG) {
-                                Log.d(TAG, "onWindowLostFocus, hiding IME because "
-                                        + "of STATE_ALWAYS_HIDDEN");
-                            }
-                            mCurRootView.getInsetsController().hide(WindowInsets.Type.ime(),
-                                    false /* fromIme */, statsToken);
-                        }
-                    }
-
                     clearCurRootViewIfNeeded();
                 }
             }
@@ -1012,6 +991,26 @@
         @GuardedBy("mH")
         private void setCurrentRootViewLocked(ViewRootImpl rootView) {
             final boolean wasEmpty = mCurRootView == null;
+            if (Flags.refactorInsetsController() && !wasEmpty && mCurRootView != rootView) {
+                final int softInputMode = mCurRootView.mWindowAttributes.softInputMode;
+                final int state =
+                        softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE;
+                if (state == WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) {
+                    // when losing input focus (e.g., by going to another window), we reset the
+                    // requestedVisibleTypes of WindowInsetsController by hiding the IME
+                    final var statsToken = ImeTracker.forLogging().onStart(
+                            ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT,
+                            SoftInputShowHideReason.HIDE_WINDOW_LOST_FOCUS,
+                            false /* fromUser */);
+                    if (DEBUG) {
+                        Log.d(TAG, "setCurrentRootViewLocked, hiding IME because "
+                                + "of STATE_ALWAYS_HIDDEN");
+                    }
+                    mCurRootView.getInsetsController().hide(WindowInsets.Type.ime(),
+                            false /* fromIme */, statsToken);
+                }
+            }
+
             mImeDispatcher.switchRootView(mCurRootView, rootView);
             mCurRootView = rootView;
             if (wasEmpty && mCurRootView != null) {
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index e600b4f..e7fa510 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -59,6 +59,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.flags.Flags;
 
 import com.android.internal.R;
 
@@ -790,7 +791,11 @@
         paint.setAntiAlias(true);
         paint.setTextAlign(Align.CENTER);
         paint.setTextSize(mTextSize);
-        paint.setTypeface(mInputText.getTypeface());
+        if (Flags.fixUnboldedTypefaceForNumberpicker()) {
+            paint.setTypeface(mInputText.getPaint().getTypeface());
+        } else {
+            paint.setTypeface(mInputText.getTypeface());
+        }
         ColorStateList colors = mInputText.getTextColors();
         int color = colors.getColorForState(ENABLED_STATE_SET, Color.WHITE);
         paint.setColor(color);
diff --git a/core/java/android/widget/flags/flags.aconfig b/core/java/android/widget/flags/flags.aconfig
index d9dc36c..88eb043 100644
--- a/core/java/android/widget/flags/flags.aconfig
+++ b/core/java/android/widget/flags/flags.aconfig
@@ -17,3 +17,13 @@
   is_exported: true
   bug: "369480667"
 }
+
+flag {
+  name: "fix_unbolded_typeface_for_numberpicker"
+  namespace: "text"
+  description: "Use the correct bolded typeface when drawing the selector numbers"
+  bug: "318304896"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 5397da1..435c8c7 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -44,20 +44,16 @@
 import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.GraphicBuffer;
 import android.graphics.Paint;
-import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
 import android.os.IBinder;
 import android.util.Log;
-import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.ViewGroup;
 import android.view.WindowInsets;
@@ -66,7 +62,6 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.DecorView;
-import com.android.window.flags.Flags;
 
 /**
  * Utils class to help draw a snapshot on a surface.
@@ -103,8 +98,6 @@
             | FLAG_SECURE
             | FLAG_DIM_BEHIND;
 
-    private static final Paint sBackgroundPaint = new Paint();
-
     /**
      * The internal object to hold the surface and drawing on it.
      */
@@ -115,54 +108,29 @@
         private final TaskSnapshot mSnapshot;
         private final CharSequence mTitle;
 
-        private SystemBarBackgroundPainter mSystemBarBackgroundPainter;
-        private final Rect mFrame = new Rect();
-        private final Rect mSystemBarInsets = new Rect();
         private final int mSnapshotW;
         private final int mSnapshotH;
-        private boolean mSizeMismatch;
+        private final int mContainerW;
+        private final int mContainerH;
 
         public SnapshotSurface(SurfaceControl rootSurface, TaskSnapshot snapshot,
-                CharSequence title) {
+                Rect windowBounds, CharSequence title) {
             mRootSurface = rootSurface;
             mSnapshot = snapshot;
             mTitle = title;
             final HardwareBuffer hwBuffer = snapshot.getHardwareBuffer();
             mSnapshotW = hwBuffer.getWidth();
             mSnapshotH = hwBuffer.getHeight();
-        }
-
-        /**
-         * Initiate system bar painter to draw the system bar background.
-         */
-        @VisibleForTesting
-        public void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
-                int appearance, ActivityManager.TaskDescription taskDescription,
-                @WindowInsets.Type.InsetsType int requestedVisibleTypes) {
-            mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
-                    windowPrivateFlags, appearance, taskDescription, 1f, requestedVisibleTypes);
-            int backgroundColor = taskDescription.getBackgroundColor();
-            sBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
-        }
-
-        /**
-         * Set frame size that the snapshot should fill. It is the bounds of a task or activity.
-         */
-        @VisibleForTesting
-        public void setFrames(Rect frame, Rect systemBarInsets) {
-            mFrame.set(frame);
-            final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
-            mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH)
-                    || letterboxInsets.left != 0 || letterboxInsets.top != 0;
-            if (!Flags.drawSnapshotAspectRatioMatch() && systemBarInsets != null) {
-                mSystemBarInsets.set(systemBarInsets);
-                mSystemBarBackgroundPainter.setInsets(systemBarInsets);
-            }
+            mContainerW = windowBounds.width();
+            mContainerH = windowBounds.height();
         }
 
         private void drawSnapshot(boolean releaseAfterDraw) {
-            Log.v(TAG, "Drawing snapshot surface sizeMismatch=" + mSizeMismatch);
-            if (mSizeMismatch) {
+            final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
+            final boolean sizeMismatch = mContainerW != mSnapshotW || mContainerH != mSnapshotH
+                    || letterboxInsets.left != 0 || letterboxInsets.top != 0;
+            Log.v(TAG, "Drawing snapshot surface sizeMismatch=" + sizeMismatch);
+            if (sizeMismatch) {
                 // The dimensions of the buffer and the window don't match, so attaching the buffer
                 // will fail. Better create a child window with the exact dimensions and fill the
                 // parent window with the background color!
@@ -189,11 +157,6 @@
         private void drawSizeMismatchSnapshot() {
             final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
 
-            // We consider nearly matched dimensions as there can be rounding errors and the user
-            // won't notice very minute differences from scaling one dimension more than the other
-            boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshotW, mSnapshotH)
-                    && !Flags.drawSnapshotAspectRatioMatch();
-
             // Keep a reference to it such that it doesn't get destroyed when finalized.
             SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
                     .setName(mTitle + " - task-snapshot-surface")
@@ -203,166 +166,28 @@
                     .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot")
                     .build();
 
-            final Rect frame;
             final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
             float offsetX = letterboxInsets.left;
             float offsetY = letterboxInsets.top;
             // We can just show the surface here as it will still be hidden as the parent is
             // still hidden.
             mTransaction.show(childSurfaceControl);
-            if (aspectRatioMismatch) {
-                Rect crop = null;
-                if (letterboxInsets.left != 0 || letterboxInsets.top != 0
-                        || letterboxInsets.right != 0 || letterboxInsets.bottom != 0) {
-                    // Clip off letterbox.
-                    crop = calculateSnapshotCrop(letterboxInsets);
-                    // If the snapshot can cover the frame, then no need to draw background.
-                    aspectRatioMismatch = !isAspectRatioMatch(mFrame, crop);
-                }
-                // if letterbox doesn't match window frame, try crop by content insets
-                if (aspectRatioMismatch) {
-                    // Clip off ugly navigation bar.
-                    final Rect contentInsets = mSnapshot.getContentInsets();
-                    crop = calculateSnapshotCrop(contentInsets);
-                    offsetX = contentInsets.left;
-                    offsetY = contentInsets.top;
-                }
-                frame = calculateSnapshotFrame(crop);
-                mTransaction.setCrop(childSurfaceControl, crop);
-            } else {
-                frame = null;
-            }
 
             // Align the snapshot with content area.
             if (offsetX != 0f || offsetY != 0f) {
                 mTransaction.setPosition(childSurfaceControl,
-                        -offsetX * mFrame.width() / mSnapshot.getTaskSize().x,
-                        -offsetY * mFrame.height() / mSnapshot.getTaskSize().y);
+                        -offsetX * mContainerW / mSnapshot.getTaskSize().x,
+                        -offsetY * mContainerH / mSnapshot.getTaskSize().y);
             }
             // Scale the mismatch dimensions to fill the target frame.
-            final float scaleX = (float) mFrame.width() / mSnapshotW;
-            final float scaleY = (float) mFrame.height() / mSnapshotH;
+            final float scaleX = (float) mContainerW / mSnapshotW;
+            final float scaleY = (float) mContainerH / mSnapshotH;
             mTransaction.setScale(childSurfaceControl, scaleX, scaleY);
             mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
             mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
-
-            if (aspectRatioMismatch) {
-                GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(),
-                        PixelFormat.RGBA_8888,
-                        GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
-                                | GraphicBuffer.USAGE_SW_WRITE_RARELY);
-                final Canvas c = background != null ? background.lockCanvas() : null;
-                if (c == null) {
-                    Log.e(TAG, "Unable to draw snapshot: failed to allocate graphic buffer for "
-                            + mTitle);
-                    mTransaction.clear();
-                    childSurfaceControl.release();
-                    return;
-                }
-                drawBackgroundAndBars(c, frame);
-                background.unlockCanvasAndPost(c);
-                mTransaction.setBuffer(mRootSurface,
-                        HardwareBuffer.createFromGraphicBuffer(background));
-            }
             mTransaction.apply();
             childSurfaceControl.release();
         }
-
-        /**
-         * Calculates the snapshot crop in snapshot coordinate space.
-         * @param insets Content insets or Letterbox insets
-         * @return crop rect in snapshot coordinate space.
-         */
-        @VisibleForTesting
-        public Rect calculateSnapshotCrop(@NonNull Rect insets) {
-            final Rect rect = new Rect();
-            rect.set(0, 0, mSnapshotW, mSnapshotH);
-
-            final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
-            final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
-
-            // Let's remove all system decorations except the status bar, but only if the task is at
-            // the very top of the screen.
-            final boolean isTop = mFrame.top == 0;
-            rect.inset((int) (insets.left * scaleX),
-                    isTop ? 0 : (int) (insets.top * scaleY),
-                    (int) (insets.right * scaleX),
-                    (int) (insets.bottom * scaleY));
-            return rect;
-        }
-
-        /**
-         * Calculates the snapshot frame in window coordinate space from crop.
-         *
-         * @param crop rect that is in snapshot coordinate space.
-         */
-        @VisibleForTesting
-        public Rect calculateSnapshotFrame(Rect crop) {
-            final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
-            final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
-
-            // Rescale the frame from snapshot to window coordinate space
-            final Rect frame = new Rect(0, 0,
-                    (int) (crop.width() / scaleX + 0.5f),
-                    (int) (crop.height() / scaleY + 0.5f)
-            );
-
-            // However, we also need to make space for the navigation bar on the left side.
-            frame.offset(mSystemBarInsets.left, 0);
-            return frame;
-        }
-
-        /**
-         * Draw status bar and navigation bar background.
-         */
-        @VisibleForTesting
-        public void drawBackgroundAndBars(Canvas c, Rect frame) {
-            final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
-            final boolean fillHorizontally = c.getWidth() > frame.right;
-            final boolean fillVertically = c.getHeight() > frame.bottom;
-            if (fillHorizontally) {
-                c.drawRect(frame.right, alpha(mSystemBarBackgroundPainter.mStatusBarColor) == 0xFF
-                        ? statusBarHeight : 0, c.getWidth(), fillVertically
-                        ? frame.bottom : c.getHeight(), sBackgroundPaint);
-            }
-            if (fillVertically) {
-                c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), sBackgroundPaint);
-            }
-            mSystemBarBackgroundPainter.drawDecors(c, frame);
-        }
-
-        /**
-         * Ask system bar background painter to draw status bar background.
-         */
-        @VisibleForTesting
-        public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
-            mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
-                    mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
-        }
-
-        /**
-         * Ask system bar background painter to draw navigation bar background.
-         */
-        @VisibleForTesting
-        public void drawNavigationBarBackground(Canvas c) {
-            mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
-        }
-    }
-
-    private static boolean isAspectRatioMatch(Rect frame, int w, int h) {
-        if (frame.isEmpty()) {
-            return false;
-        }
-        return Math.abs(((float) w / h) - ((float) frame.width() / frame.height())) <= 0.01f;
-    }
-
-    private static boolean isAspectRatioMatch(Rect frame1, Rect frame2) {
-        if (frame1.isEmpty() || frame2.isEmpty()) {
-            return false;
-        }
-        return Math.abs(
-                ((float) frame2.width() / frame2.height())
-                        - ((float) frame1.width() / frame1.height())) <= 0.01f;
     }
 
     /**
@@ -383,28 +208,15 @@
     /**
      * Help method to draw the snapshot on a surface.
      */
-    public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
+    public static void drawSnapshotOnSurface(WindowManager.LayoutParams lp,
             SurfaceControl rootSurface, TaskSnapshot snapshot,
-            Rect windowBounds, InsetsState topWindowInsetsState,
-            boolean releaseAfterDraw) {
+            Rect windowBounds, boolean releaseAfterDraw) {
         if (windowBounds.isEmpty()) {
             Log.e(TAG, "Unable to draw snapshot on an empty windowBounds");
             return;
         }
         final SnapshotSurface drawSurface = new SnapshotSurface(
-                rootSurface, snapshot, lp.getTitle());
-        final WindowManager.LayoutParams attrs = Flags.drawSnapshotAspectRatioMatch()
-                ? info.mainWindowLayoutParams : info.topOpaqueWindowLayoutParams;
-        final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
-        final ActivityManager.TaskDescription taskDescription =
-                getOrCreateTaskDescription(runningTaskInfo);
-        Rect systemBarInsets = null;
-        if (!Flags.drawSnapshotAspectRatioMatch()) {
-            drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
-                    attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
-            systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
-        }
-        drawSurface.setFrames(windowBounds, systemBarInsets);
+                rootSurface, snapshot, windowBounds, lp.getTitle());
         drawSurface.drawSnapshot(releaseAfterDraw);
     }
 
@@ -414,10 +226,8 @@
     public static WindowManager.LayoutParams createLayoutParameters(StartingWindowInfo info,
             CharSequence title, @WindowManager.LayoutParams.WindowType int windowType,
             int pixelFormat, IBinder token) {
-        final WindowManager.LayoutParams attrs = Flags.drawSnapshotAspectRatioMatch()
-                ? info.mainWindowLayoutParams : info.topOpaqueWindowLayoutParams;
-        final WindowManager.LayoutParams mainWindowParams = info.mainWindowLayoutParams;
-        if (attrs == null || mainWindowParams == null) {
+        final WindowManager.LayoutParams attrs = info.mainWindowLayoutParams;
+        if (attrs == null) {
             Log.w(TAG, "unable to create taskSnapshot surface ");
             return null;
         }
@@ -427,9 +237,9 @@
         final int windowFlags = attrs.flags;
         final int windowPrivateFlags = attrs.privateFlags;
 
-        layoutParams.packageName = mainWindowParams.packageName;
-        layoutParams.windowAnimations = mainWindowParams.windowAnimations;
-        layoutParams.dimAmount = mainWindowParams.dimAmount;
+        layoutParams.packageName = attrs.packageName;
+        layoutParams.windowAnimations = attrs.windowAnimations;
+        layoutParams.dimAmount = attrs.dimAmount;
         layoutParams.type = windowType;
         layoutParams.format = pixelFormat;
         layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
@@ -460,14 +270,6 @@
         return layoutParams;
     }
 
-    static Rect getSystemBarInsets(Rect frame, @Nullable InsetsState state) {
-        if (state == null) {
-            return new Rect();
-        }
-        return state.calculateInsets(frame, WindowInsets.Type.systemBars(),
-                false /* ignoreVisibility */).toRect();
-    }
-
     /**
      * Helper class to draw the background of the system bars in regions the task snapshot isn't
      * filling the window.
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 72df343..80ccbdd 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -27,7 +27,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
-import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
@@ -100,20 +99,6 @@
     public ActivityInfo targetActivityInfo;
 
     /**
-     * InsetsState of TopFullscreenOpaqueWindow
-     * @hide
-     */
-    @Nullable
-    public InsetsState topOpaqueWindowInsetsState;
-
-    /**
-     * LayoutParams of TopFullscreenOpaqueWindow
-     * @hide
-     */
-    @Nullable
-    public WindowManager.LayoutParams topOpaqueWindowLayoutParams;
-
-    /**
      * LayoutParams of MainWindow
      * @hide
      */
@@ -263,8 +248,6 @@
         taskBounds.writeToParcel(dest, flags);
         dest.writeTypedObject(targetActivityInfo, flags);
         dest.writeInt(startingWindowTypeParameter);
-        dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
-        dest.writeTypedObject(topOpaqueWindowLayoutParams, flags);
         dest.writeTypedObject(mainWindowLayoutParams, flags);
         dest.writeInt(splashScreenThemeResId);
         dest.writeBoolean(isKeyguardOccluded);
@@ -280,9 +263,6 @@
         taskBounds.readFromParcel(source);
         targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
         startingWindowTypeParameter = source.readInt();
-        topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
-        topOpaqueWindowLayoutParams = source.readTypedObject(
-                WindowManager.LayoutParams.CREATOR);
         mainWindowLayoutParams = source.readTypedObject(WindowManager.LayoutParams.CREATOR);
         splashScreenThemeResId = source.readInt();
         isKeyguardOccluded = source.readBoolean();
@@ -302,8 +282,6 @@
                 + " topActivityType=" + taskInfo.topActivityType
                 + " preferredStartingWindowType="
                 + Integer.toHexString(startingWindowTypeParameter)
-                + " insetsState=" + topOpaqueWindowInsetsState
-                + " topWindowLayoutParams=" + topOpaqueWindowLayoutParams
                 + " mainWindowLayoutParams=" + mainWindowLayoutParams
                 + " splashScreenThemeResId " + Integer.toHexString(splashScreenThemeResId);
     }
diff --git a/core/java/android/window/WindowTokenClientController.java b/core/java/android/window/WindowTokenClientController.java
index 1ec05b6..fcd7dfb 100644
--- a/core/java/android/window/WindowTokenClientController.java
+++ b/core/java/android/window/WindowTokenClientController.java
@@ -35,6 +35,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
 
 /**
  * Singleton controller to manage the attached {@link WindowTokenClient}s, and to dispatch
@@ -137,7 +138,9 @@
             // is initialized later, the SystemUiContext will start reporting from
             // DisplayContent#registerSystemUiContext, and WindowTokenClientController can report
             // the Configuration to the correct client.
-            recordWindowContextToken(client);
+            if (Flags.trackSystemUiContextBeforeWms()) {
+                recordWindowContextToken(client);
+            }
             return false;
         }
         final WindowContextInfo info;
@@ -145,6 +148,9 @@
             info = wms.attachWindowContextToDisplayContent(mAppThread, client, displayId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (Exception e) {
+            Log.e(TAG, "Failed attachToDisplayContent", e);
+            return false;
         }
         if (info == null) {
             return false;
diff --git a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
index 801698c..a42759e 100644
--- a/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
+++ b/core/java/android/window/flags/large_screen_experiences_app_compat.aconfig
@@ -2,10 +2,10 @@
 container: "system"
 
 flag {
-  name: "disable_thin_letterboxing_policy"
+  name: "ignore_aspect_ratio_restrictions_for_resizeable_freeform_activities"
   namespace: "large_screen_experiences_app_compat"
-  description: "Whether reachability is disabled in case of thin letterboxing"
-  bug: "341027847"
+  description: "If a resizeable activity enters freeform mode, ignore all aspect ratio constraints."
+  bug: "381866902"
   metadata {
     purpose: PURPOSE_BUGFIX
   }
@@ -58,13 +58,6 @@
 }
 
 flag {
-  name: "user_min_aspect_ratio_app_default"
-  namespace: "large_screen_experiences_app_compat"
-  description: "Whether the API PackageManager.USER_MIN_ASPECT_RATIO_APP_DEFAULT is available"
-  bug: "310816437"
-}
-
-flag {
   name: "allow_hide_scm_button"
   namespace: "large_screen_experiences_app_compat"
   description: "Whether we should allow hiding the size compat restart button"
@@ -80,16 +73,6 @@
 }
 
 flag {
-  name: "immersive_app_repositioning"
-  namespace: "large_screen_experiences_app_compat"
-  description: "Fix immersive apps changing size when repositioning"
-  bug: "334076352"
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-flag {
   name: "camera_compat_for_freeform"
   namespace: "large_screen_experiences_app_compat"
   description: "Whether to apply Camera Compat treatment to fixed-orientation apps in freeform windowing mode"
@@ -162,4 +145,14 @@
   description: "Whether the API for forcing apps to be universal resizable on virtual display is available"
   bug: "372848702"
   is_exported: true
+}
+
+flag {
+  name: "release_user_aspect_ratio_wm"
+  namespace: "large_screen_experiences_app_compat"
+  description: "Whether to release UserAspectRatioSettingsWindowManager when button is hidden"
+  bug: "385049711"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
 }
\ No newline at end of file
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 3b77b1f..ccb1e2b 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -485,6 +485,13 @@
 }
 
 flag {
+    name: "enable_multiple_desktops_backend"
+    namespace: "lse_desktop_experience"
+    description: "Enable multiple desktop sessions for desktop windowing (backend)."
+    bug: "362720497"
+}
+
+flag {
     name: "enable_connected_displays_dnd"
     namespace: "lse_desktop_experience"
     description: "Enable drag-and-drop between connected displays."
@@ -521,4 +528,11 @@
     namespace: "lse_desktop_experience"
     description: "Enables having a DesktopWallpaperActivity at a per-display level."
     bug: "381935663"
+}
+
+flag {
+    name: "enable_desktop_wallpaper_activity_on_system_user"
+    namespace: "lse_desktop_experience"
+    description: "Enables starting DesktopWallpaperActivity on system user."
+    bug: "385294350"
 }
\ No newline at end of file
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 30668a6..7eabd17 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -235,6 +235,17 @@
 }
 
 flag {
+  name: "scheduling_for_notification_shade"
+  namespace: "windowing_frontend"
+  description: "Demote top-app when notification shade is expanded"
+  bug: "362467878"
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
     name: "release_snapshot_aggressively"
     namespace: "windowing_frontend"
     description: "Actively release task snapshot memory"
@@ -243,17 +254,6 @@
 }
 
 flag {
-  name: "draw_snapshot_aspect_ratio_match"
-  namespace: "windowing_frontend"
-  description: "The aspect ratio should always match when drawing snapshot"
-  bug: "341020277"
-  is_fixed_read_only: true
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-flag {
   name: "system_ui_post_animation_end"
   namespace: "windowing_frontend"
   description: "Run AnimatorListener#onAnimationEnd on next frame for SystemUI"
@@ -379,17 +379,6 @@
 }
 
 flag {
-  name: "disallow_app_progress_embedded_window"
-  namespace: "windowing_frontend"
-  description: "Pilfer pointers when app transfer input gesture to embedded window."
-  bug: "365504126"
-  is_fixed_read_only: true
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-flag {
     name: "predictive_back_system_override_callback"
     namespace: "windowing_frontend"
     description: "Provide pre-make predictive back API extension"
@@ -441,4 +430,23 @@
   description: "Support insets definition and calculation relative to task bounds."
   bug: "277292497"
   is_fixed_read_only: true
-}
\ No newline at end of file
+}
+
+flag {
+    name: "exclude_drawing_app_theme_snapshot_from_lock"
+    namespace: "windowing_frontend"
+    description: "Do not hold wm lock when drawing app theme snapshot."
+    is_fixed_read_only: true
+    bug: "373502791"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "port_window_size_animation"
+    namespace: "systemui"
+    description: "Port window-resize animation from legacy to shell"
+    bug: "384976265"
+}
+
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 5a092b8..abd93cf 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -105,6 +105,13 @@
 
 flag {
     namespace: "windowing_sdk"
+    name: "activity_embedding_support_for_connected_displays"
+    description: "Enables activity embedding support for connected displays, including enabling AE optimization for Settings."
+    bug: "369438353"
+}
+
+flag {
+    namespace: "windowing_sdk"
     name: "wlinfo_oncreate"
     description: "Makes WindowLayoutInfo accessible without racing in the Activity#onCreate()"
     bug: "337820752"
@@ -138,3 +145,23 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    namespace: "windowing_sdk"
+    name: "normalize_home_intent"
+    description: "To ensure home is started in correct intent"
+    bug: "378505461"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    namespace: "windowing_sdk"
+    name: "condense_configuration_change_for_simple_mode"
+    description: "Condense configuration change for simple mode"
+    bug: "356738240"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 2cfc680..f01aa80 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -163,4 +163,5 @@
     void finishOperationForDevice(IBinder clientId, int code, int uid, String packageName,
             @nullable String attributionTag, int virtualDeviceId);
    List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(in int[] ops, String persistentDeviceId);
+   oneway void noteOperationsInBatch(in Map batchedNoteOps);
 }
diff --git a/core/java/com/android/internal/app/ProcessMap.java b/core/java/com/android/internal/app/ProcessMap.java
index 542b6d0..b4945e7 100644
--- a/core/java/com/android/internal/app/ProcessMap.java
+++ b/core/java/com/android/internal/app/ProcessMap.java
@@ -28,6 +28,11 @@
         if (uids == null) return null;
         return uids.get(uid);
     }
+
+    public SparseArray<E> get(String name) {
+        SparseArray<E> uids = mMap.get(name);
+        return uids;
+    }
     
     public E put(String name, int uid, E value) {
         SparseArray<E> uids = mMap.get(name);
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index a50dbb0..50f1000 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -601,7 +601,7 @@
             cr.registerContentObserver(BRIGHTNESS_URI, false,
                     createBrightnessContentObserver(handler), UserHandle.USER_ALL);
             mDisplayManager.registerDisplayListener(mListener, handler, /* eventFlags */ 0,
-                    DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
+                    DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS);
             mIsObserving = true;
         }
     }
diff --git a/core/java/com/android/internal/jank/DisplayResolutionTracker.java b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
index 0c2fd4b..5d66b3c 100644
--- a/core/java/com/android/internal/jank/DisplayResolutionTracker.java
+++ b/core/java/com/android/internal/jank/DisplayResolutionTracker.java
@@ -148,8 +148,8 @@
                 public void registerDisplayListener(DisplayManager.DisplayListener listener) {
                     manager.registerDisplayListener(listener, handler,
                             DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-                                    | DisplayManagerGlobal
-                                            .INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+                                    | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                                    | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                             ActivityThread.currentPackageName());
                 }
 
diff --git a/core/java/com/android/internal/policy/KeyInterceptionInfo.java b/core/java/com/android/internal/policy/KeyInterceptionInfo.java
index b20f6d2..fed8fe3 100644
--- a/core/java/com/android/internal/policy/KeyInterceptionInfo.java
+++ b/core/java/com/android/internal/policy/KeyInterceptionInfo.java
@@ -27,11 +27,13 @@
     // Debug friendly name to help identify the window
     public final String windowTitle;
     public final int windowOwnerUid;
+    public final int inputFeaturesFlags;
 
-    public KeyInterceptionInfo(int type, int flags, String title, int uid) {
+    public KeyInterceptionInfo(int type, int flags, String title, int uid, int inputFeaturesFlags) {
         layoutParamsType = type;
         layoutParamsPrivateFlags = flags;
         windowTitle = title;
         windowOwnerUid = uid;
+        this.inputFeaturesFlags = inputFeaturesFlags;
     }
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 3e2f301..f14e1f6 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -236,4 +236,7 @@
 
     /** Shows rear display educational dialog */
     void showRearDisplayDialog(int currentBaseState);
+
+    /** Unbundle a categorized notification */
+    void unbundleNotification(String key);
 }
diff --git a/core/java/com/android/internal/util/LATENCY_TRACKER_OWNERS b/core/java/com/android/internal/util/LATENCY_TRACKER_OWNERS
index 7755000..3ed902f 100644
--- a/core/java/com/android/internal/util/LATENCY_TRACKER_OWNERS
+++ b/core/java/com/android/internal/util/LATENCY_TRACKER_OWNERS
@@ -1,3 +1,5 @@
 # TODO(b/274465475): Migrate LatencyTracker testing to its own module
 marcinoc@google.com
 ilkos@google.com
+jjaggi@google.com
+nicomazz@google.com
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index d49afa7..f443b0a 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -38,6 +38,7 @@
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR;
+import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_BACK_ARROW;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_SELECTION_TOOLBAR;
 import static com.android.internal.util.FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHOW_VOICE_INTERACTION;
@@ -257,6 +258,14 @@
      */
     public static final int ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME = 28;
 
+    /**
+     * Time it takes for the shade window to move display after a user interaction.
+     * <p>
+     * This starts when the user does an interaction that triggers the window reparenting, and
+     * finishes after the first doFrame done with the new display configuration.
+     */
+    public static final int ACTION_SHADE_WINDOW_DISPLAY_CHANGE = 29;
+
     private static final int[] ACTIONS_ALL = {
         ACTION_EXPAND_PANEL,
         ACTION_TOGGLE_RECENTS,
@@ -287,6 +296,7 @@
         ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE,
         ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
         ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
+        ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
     };
 
     /** @hide */
@@ -320,6 +330,7 @@
         ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE,
         ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
         ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
+        ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Action {
@@ -356,6 +367,7 @@
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN,
             UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME,
+            UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE,
     };
 
     private final Object mLock = new Object();
@@ -554,6 +566,8 @@
                 return "ACTION_NOTIFICATIONS_HIDDEN_FOR_MEASURE_WITH_SHADE_OPEN";
             case UIACTION_LATENCY_REPORTED__ACTION__ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME:
                 return "ACTION_KEYGUARD_FACE_UNLOCK_TO_HOME";
+            case UIACTION_LATENCY_REPORTED__ACTION__ACTION_SHADE_WINDOW_DISPLAY_CHANGE:
+                return "ACTION_SHADE_WINDOW_DISPLAY_CHANGE";
             default:
                 throw new IllegalArgumentException("Invalid action");
         }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 9bd5237..39ddea6 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -25,6 +25,8 @@
 import static android.security.Flags.reportPrimaryAuthAttempts;
 import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth;
 
+import static com.android.internal.widget.flags.Flags.hideLastCharWithPhysicalInput;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -42,6 +44,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.hardware.input.InputManagerGlobal;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -59,6 +62,7 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.SparseLongArray;
+import android.view.InputDevice;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
@@ -1097,12 +1101,20 @@
         return type == CREDENTIAL_TYPE_PATTERN;
     }
 
+    private boolean hasActivePointerDeviceAttached() {
+        return !getEnabledNonTouchInputDevices(InputDevice.SOURCE_CLASS_POINTER).isEmpty();
+    }
+
     /**
      * @return Whether the visible pattern is enabled.
      */
     @UnsupportedAppUsage
     public boolean isVisiblePatternEnabled(int userId) {
-        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, true, userId);
+        boolean defaultValue = true;
+        if (hideLastCharWithPhysicalInput()) {
+            defaultValue = !hasActivePointerDeviceAttached();
+        }
+        return getBoolean(Settings.Secure.LOCK_PATTERN_VISIBLE, defaultValue, userId);
     }
 
     /**
@@ -1116,11 +1128,39 @@
         return getString(Settings.Secure.LOCK_PATTERN_VISIBLE, userId) != null;
     }
 
+    private List<InputDevice> getEnabledNonTouchInputDevices(int source) {
+        final InputManagerGlobal inputManager = InputManagerGlobal.getInstance();
+        final int[] inputIds = inputManager.getInputDeviceIds();
+        List<InputDevice> matchingDevices = new ArrayList<InputDevice>();
+        for (final int deviceId : inputIds) {
+            final InputDevice inputDevice = inputManager.getInputDevice(deviceId);
+            if (!inputDevice.isEnabled()) continue;
+            if (inputDevice.supportsSource(InputDevice.SOURCE_TOUCHSCREEN)) continue;
+            if (inputDevice.isVirtual()) continue;
+            if (!inputDevice.supportsSource(source)) continue;
+            matchingDevices.add(inputDevice);
+        }
+        return matchingDevices;
+    }
+
+    private boolean hasPhysicalKeyboardActive() {
+        final List<InputDevice> keyboards =
+                getEnabledNonTouchInputDevices(InputDevice.SOURCE_KEYBOARD);
+        for (final InputDevice keyboard : keyboards) {
+            if (keyboard.isFullKeyboard()) return true;
+        }
+        return false;
+    }
+
     /**
      * @return Whether enhanced pin privacy is enabled.
      */
     public boolean isPinEnhancedPrivacyEnabled(int userId) {
-        return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, false, userId);
+        boolean defaultValue = false;
+        if (hideLastCharWithPhysicalInput()) {
+            defaultValue = hasPhysicalKeyboardActive();
+        }
+        return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, defaultValue, userId);
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index d4dd1e7..751cfde 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.widget;
 
+import static android.app.Flags.notificationsRedesignTemplates;
+
 import android.annotation.ColorInt;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -130,10 +132,18 @@
         int drawableId;
         int contentDescriptionId;
         if (mExpanded) {
-            drawableId = R.drawable.ic_collapse_notification;
+            if (notificationsRedesignTemplates()) {
+                drawableId = R.drawable.ic_notification_2025_collapse;
+            } else {
+                drawableId = R.drawable.ic_collapse_notification;
+            }
             contentDescriptionId = R.string.expand_button_content_description_expanded;
         } else {
-            drawableId = R.drawable.ic_expand_notification;
+            if (notificationsRedesignTemplates()) {
+                drawableId = R.drawable.ic_notification_2025_expand;
+            } else {
+                drawableId = R.drawable.ic_expand_notification;
+            }
             contentDescriptionId = R.string.expand_button_content_description_collapsed;
         }
         setContentDescription(mContext.getText(contentDescriptionId));
diff --git a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
index 39a2ab3..43118a0 100644
--- a/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
+++ b/core/java/com/android/internal/widget/remotecompose/accessibility/PlatformRemoteComposeTouchHelper.java
@@ -30,7 +30,7 @@
 import com.android.internal.widget.remotecompose.core.CoreDocument;
 import com.android.internal.widget.remotecompose.core.operations.layout.Component;
 import com.android.internal.widget.remotecompose.core.semantics.AccessibilitySemantics;
-import com.android.internal.widget.remotecompose.core.semantics.CoreSemantics.Mode;
+import com.android.internal.widget.remotecompose.core.semantics.AccessibleComponent.Mode;
 
 import java.util.HashSet;
 import java.util.List;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
index 60767ed..26b0d11 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/CoreDocument.java
@@ -62,7 +62,7 @@
 
     // We also keep a more fine-grained BUILD number, exposed as
     // ID_API_LEVEL = DOCUMENT_API_LEVEL + BUILD
-    static final float BUILD = 0.0f;
+    static final float BUILD = 0.2f;
 
     @NonNull ArrayList<Operation> mOperations = new ArrayList<>();
 
@@ -123,6 +123,11 @@
         return mWidth;
     }
 
+    /**
+     * Set the viewport width of the document
+     *
+     * @param width document width
+     */
     public void setWidth(int width) {
         this.mWidth = width;
         mRemoteComposeState.setWindowWidth(width);
@@ -132,6 +137,11 @@
         return mHeight;
     }
 
+    /**
+     * Set the viewport height of the document
+     *
+     * @param height document height
+     */
     public void setHeight(int height) {
         this.mHeight = height;
         mRemoteComposeState.setWindowHeight(height);
@@ -395,6 +405,11 @@
 
     // ============== Haptic support ==================
     public interface HapticEngine {
+        /**
+         * Implements a haptic effect
+         *
+         * @param type the type of effect
+         */
         void haptic(int type);
     }
 
@@ -404,6 +419,11 @@
         mHapticEngine = engine;
     }
 
+    /**
+     * Execute an haptic command
+     *
+     * @param type the type of haptic pre-defined effect
+     */
     public void haptic(int type) {
         if (mHapticEngine != null) {
             mHapticEngine.haptic(type);
@@ -412,12 +432,23 @@
 
     // ============== Haptic support ==================
 
-    public void appliedTouchOperation(Component operation) {
-        mAppliedTouchOperations.add(operation);
+    /**
+     * To signal that the given component will apply the touch operation
+     *
+     * @param component the component applying the touch
+     */
+    public void appliedTouchOperation(Component component) {
+        mAppliedTouchOperations.add(component);
     }
 
     /** Callback interface for host actions */
     public interface ActionCallback {
+        /**
+         * Callback for actions
+         *
+         * @param name the action name
+         * @param value the payload of the action
+         */
         void onAction(@NonNull String name, Object value);
     }
 
@@ -450,7 +481,14 @@
         mActionListeners.clear();
     }
 
+    /** Id Actions */
     public interface IdActionCallback {
+        /**
+         * Callback on Id Actions
+         *
+         * @param id the actio id triggered
+         * @param metadata optional metadata
+         */
         void onAction(int id, @Nullable String metadata);
     }
 
@@ -530,10 +568,20 @@
             return mTop;
         }
 
+        /**
+         * Returns the width of the click area
+         *
+         * @return the width of the click area
+         */
         public float width() {
             return Math.max(0, mRight - mLeft);
         }
 
+        /**
+         * Returns the height of the click area
+         *
+         * @return the height of the click area
+         */
         public float height() {
             return Math.max(0, mBottom - mTop);
         }
@@ -816,6 +864,7 @@
         for (ClickAreaRepresentation clickArea : mClickAreas) {
             if (clickArea.mId == id) {
                 warnClickListeners(clickArea);
+                return;
             }
         }
         for (IdActionCallback listener : mIdActionListeners) {
@@ -1009,7 +1058,7 @@
      * @param theme the theme we want to use for this document.
      */
     public void paint(@NonNull RemoteContext context, int theme) {
-        context.getLastOpCount();
+        context.clearLastOpCount();
         context.getPaintContext().clearNeedsRepaint();
         context.loadFloat(RemoteContext.ID_DENSITY, context.getDensity());
         context.mMode = RemoteContext.ContextMode.UNSET;
@@ -1127,6 +1176,11 @@
         return count;
     }
 
+    /**
+     * Returns a list of useful statistics for the runtime document
+     *
+     * @return
+     */
     @NonNull
     public String[] getStats() {
         ArrayList<String> ret = new ArrayList<>();
@@ -1145,8 +1199,8 @@
 
             values[0] += 1;
             values[1] += sizeOfComponent(mOperation, buffer);
-            if (mOperation instanceof Component) {
-                Component com = (Component) mOperation;
+            if (mOperation instanceof Container) {
+                Container com = (Container) mOperation;
                 count += addChildren(com, map, buffer);
             } else if (mOperation instanceof LoopOperation) {
                 LoopOperation com = (LoopOperation) mOperation;
@@ -1172,9 +1226,9 @@
     }
 
     private int addChildren(
-            @NonNull Component base, @NonNull HashMap<String, int[]> map, @NonNull WireBuffer tmp) {
-        int count = base.mList.size();
-        for (Operation mOperation : base.mList) {
+            @NonNull Container base, @NonNull HashMap<String, int[]> map, @NonNull WireBuffer tmp) {
+        int count = base.getList().size();
+        for (Operation mOperation : base.getList()) {
             Class<? extends Operation> c = mOperation.getClass();
             int[] values;
             if (map.containsKey(c.getSimpleName())) {
@@ -1185,65 +1239,42 @@
             }
             values[0] += 1;
             values[1] += sizeOfComponent(mOperation, tmp);
-            if (mOperation instanceof Component) {
-                count += addChildren((Component) mOperation, map, tmp);
-            }
-            if (mOperation instanceof LoopOperation) {
-                count += addChildren((LoopOperation) mOperation, map, tmp);
+            if (mOperation instanceof Container) {
+                count += addChildren((Container) mOperation, map, tmp);
             }
         }
         return count;
     }
 
-    private int addChildren(
-            @NonNull LoopOperation base,
-            @NonNull HashMap<String, int[]> map,
-            @NonNull WireBuffer tmp) {
-        int count = base.mList.size();
-        for (Operation mOperation : base.mList) {
-            Class<? extends Operation> c = mOperation.getClass();
-            int[] values;
-            if (map.containsKey(c.getSimpleName())) {
-                values = map.get(c.getSimpleName());
-            } else {
-                values = new int[2];
-                map.put(c.getSimpleName(), values);
-            }
-            values[0] += 1;
-            values[1] += sizeOfComponent(mOperation, tmp);
-            if (mOperation instanceof Component) {
-                count += addChildren((Component) mOperation, map, tmp);
-            }
-            if (mOperation instanceof LoopOperation) {
-                count += addChildren((LoopOperation) mOperation, map, tmp);
-            }
-        }
-        return count;
-    }
-
+    /**
+     * Returns a string representation of the operations, traversing the list of operations &
+     * containers
+     *
+     * @return
+     */
     @NonNull
     public String toNestedString() {
         StringBuilder ret = new StringBuilder();
         for (Operation mOperation : mOperations) {
             ret.append(mOperation.toString());
             ret.append("\n");
-            if (mOperation instanceof Component) {
-                toNestedString((Component) mOperation, ret, "  ");
+            if (mOperation instanceof Container) {
+                toNestedString((Container) mOperation, ret, "  ");
             }
         }
         return ret.toString();
     }
 
     private void toNestedString(
-            @NonNull Component base, @NonNull StringBuilder ret, String indent) {
-        for (Operation mOperation : base.mList) {
+            @NonNull Container base, @NonNull StringBuilder ret, String indent) {
+        for (Operation mOperation : base.getList()) {
             for (String line : mOperation.toString().split("\n")) {
                 ret.append(indent);
                 ret.append(line);
                 ret.append("\n");
             }
-            if (mOperation instanceof Component) {
-                toNestedString((Component) mOperation, ret, indent + "  ");
+            if (mOperation instanceof Container) {
+                toNestedString((Container) mOperation, ret, indent + "  ");
             }
         }
     }
@@ -1255,6 +1286,12 @@
 
     /** defines if a shader can be run */
     public interface ShaderControl {
+        /**
+         * validate if a shader can run in the document
+         *
+         * @param shader the source of the shader
+         * @return true if the shader is allowed to run
+         */
         boolean isShaderValid(String shader);
     }
 
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Operations.java b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
index d9f12cb..9a37a22 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Operations.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Operations.java
@@ -55,6 +55,8 @@
 import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate;
 import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
 import com.android.internal.widget.remotecompose.core.operations.PaintData;
+import com.android.internal.widget.remotecompose.core.operations.ParticlesCreate;
+import com.android.internal.widget.remotecompose.core.operations.ParticlesLoop;
 import com.android.internal.widget.remotecompose.core.operations.PathAppend;
 import com.android.internal.widget.remotecompose.core.operations.PathCreate;
 import com.android.internal.widget.remotecompose.core.operations.PathData;
@@ -75,6 +77,8 @@
 import com.android.internal.widget.remotecompose.core.operations.layout.ClickModifierOperation;
 import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart;
 import com.android.internal.widget.remotecompose.core.operations.layout.ContainerEnd;
+import com.android.internal.widget.remotecompose.core.operations.layout.ImpulseOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.ImpulseProcess;
 import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent;
 import com.android.internal.widget.remotecompose.core.operations.layout.LoopOperation;
 import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
@@ -188,6 +192,11 @@
     public static final int PATH_TWEEN = 158;
     public static final int PATH_CREATE = 159;
     public static final int PATH_ADD = 160;
+    public static final int PARTICLE_CREATE = 161;
+    public static final int PARTICLE_PROCESS = 162;
+    public static final int PARTICLE_LOOP = 163;
+    public static final int IMPULSE_START = 164;
+    public static final int IMPULSE_PROCESS = 165;
 
     ///////////////////////////////////////// ======================
 
@@ -366,6 +375,10 @@
         map.put(PATH_TWEEN, PathTween::read);
         map.put(PATH_CREATE, PathCreate::read);
         map.put(PATH_ADD, PathAppend::read);
+        map.put(IMPULSE_START, ImpulseOperation::read);
+        map.put(IMPULSE_PROCESS, ImpulseProcess::read);
+        map.put(PARTICLE_CREATE, ParticlesCreate::read);
+        map.put(PARTICLE_LOOP, ParticlesLoop::read);
 
         map.put(ACCESSIBILITY_SEMANTICS, CoreSemantics::read);
         //        map.put(ACCESSIBILITY_CUSTOM_ACTION, CoreSemantics::read);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
index 4a40a31..49a0457 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintContext.java
@@ -33,10 +33,16 @@
         return mContext;
     }
 
+    /**
+     * Returns true if the needsRepaint flag is set
+     *
+     * @return true if the document asks to be repainted
+     */
     public boolean doesNeedsRepaint() {
         return mNeedsRepaint;
     }
 
+    /** Clear the needsRepaint flag */
     public void clearNeedsRepaint() {
         mNeedsRepaint = false;
     }
@@ -65,6 +71,20 @@
         matrixSave();
     }
 
+    /**
+     * Draw a bitmap
+     *
+     * @param imageId
+     * @param srcLeft
+     * @param srcTop
+     * @param srcRight
+     * @param srcBottom
+     * @param dstLeft
+     * @param dstTop
+     * @param dstRight
+     * @param dstBottom
+     * @param cdId
+     */
     public abstract void drawBitmap(
             int imageId,
             int srcLeft,
@@ -77,26 +97,105 @@
             int dstBottom,
             int cdId);
 
+    /**
+     * scale the following commands
+     *
+     * @param scaleX horizontal scale factor
+     * @param scaleY vertical scale factor
+     */
     public abstract void scale(float scaleX, float scaleY);
 
+    /**
+     * Rotate the following commands
+     *
+     * @param translateX horizontal translation
+     * @param translateY vertical translation
+     */
     public abstract void translate(float translateX, float translateY);
 
+    /**
+     * Draw an arc
+     *
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
+     * @param startAngle
+     * @param sweepAngle
+     */
     public abstract void drawArc(
             float left, float top, float right, float bottom, float startAngle, float sweepAngle);
 
+    /**
+     * Draw a sector
+     *
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
+     * @param startAngle
+     * @param sweepAngle
+     */
     public abstract void drawSector(
             float left, float top, float right, float bottom, float startAngle, float sweepAngle);
 
+    /**
+     * Draw a bitmap
+     *
+     * @param id
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
+     */
     public abstract void drawBitmap(int id, float left, float top, float right, float bottom);
 
+    /**
+     * Draw a circle
+     *
+     * @param centerX
+     * @param centerY
+     * @param radius
+     */
     public abstract void drawCircle(float centerX, float centerY, float radius);
 
+    /**
+     * Draw a line
+     *
+     * @param x1
+     * @param y1
+     * @param x2
+     * @param y2
+     */
     public abstract void drawLine(float x1, float y1, float x2, float y2);
 
+    /**
+     * Draw an oval
+     *
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
+     */
     public abstract void drawOval(float left, float top, float right, float bottom);
 
+    /**
+     * Draw a path
+     *
+     * @param id the path id
+     * @param start starting point of the path where we start drawing it
+     * @param end ending point of the path where we stop drawing it
+     */
     public abstract void drawPath(int id, float start, float end);
 
+    /**
+     * Draw a rectangle
+     *
+     * @param left left coordinate of the rectangle
+     * @param top top coordinate of the rectangle
+     * @param right right coordinate of the rectangle
+     * @param bottom bottom coordinate of the rectangle
+     */
     public abstract void drawRect(float left, float top, float right, float bottom);
 
     /** this caches the paint to a paint stack */
@@ -105,9 +204,27 @@
     /** This restores the paint form the paint stack */
     public abstract void restorePaint();
 
+    /**
+     * draw a round rect
+     *
+     * @param left left coordinate of the rectangle
+     * @param top top coordinate of the rectangle
+     * @param right right coordinate of the rectangle
+     * @param bottom bottom coordinate of the rectangle
+     * @param radiusX horizontal radius of the rounded corner
+     * @param radiusY vertical radius of the rounded corner
+     */
     public abstract void drawRoundRect(
             float left, float top, float right, float bottom, float radiusX, float radiusY);
 
+    /**
+     * Draw the text glyphs on the provided path
+     *
+     * @param textId id of the text
+     * @param pathId id of the path
+     * @param hOffset horizontal offset
+     * @param vOffset vertical offset
+     */
     public abstract void drawTextOnPath(int textId, int pathId, float hOffset, float vOffset);
 
     /**
@@ -158,6 +275,14 @@
     public abstract void drawTweenPath(
             int path1Id, int path2Id, float tween, float start, float stop);
 
+    /**
+     * Interpolate between two path and return the resulting path
+     *
+     * @param out the interpolated path
+     * @param path1 start path
+     * @param path2 end path
+     * @param tween interpolation value from 0 (start path) to 1 (end path)
+     */
     public abstract void tweenPath(int out, int path1, int path2, float tween);
 
     /**
@@ -275,12 +400,33 @@
         System.out.println("[LOG] " + content);
     }
 
+    /** Indicates the document needs to be repainted */
     public void needsRepaint() {
         mNeedsRepaint = true;
     }
 
+    /**
+     * Starts a graphics layer
+     *
+     * @param w
+     * @param h
+     */
     public abstract void startGraphicsLayer(int w, int h);
 
+    /**
+     * Starts a graphics layer
+     *
+     * @param scaleX
+     * @param scaleY
+     * @param rotationX
+     * @param rotationY
+     * @param rotationZ
+     * @param shadowElevation
+     * @param transformOriginX
+     * @param transformOriginY
+     * @param alpha
+     * @param renderEffectId
+     */
     public abstract void setGraphicsLayer(
             float scaleX,
             float scaleY,
@@ -293,6 +439,7 @@
             float alpha,
             int renderEffectId);
 
+    /** Ends a graphics layer */
     public abstract void endGraphicsLayer();
 
     public boolean isVisualDebug() {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
index cfdd522..f355676 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/PaintOperation.java
@@ -39,6 +39,11 @@
         return indent + toString();
     }
 
+    /**
+     * Paint the operation in the context
+     *
+     * @param context painting context
+     */
     public abstract void paint(@NonNull PaintContext context);
 
     /**
diff --git a/core/java/com/android/internal/widget/remotecompose/core/Platform.java b/core/java/com/android/internal/widget/remotecompose/core/Platform.java
index dcb8efeb..e4a063d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/Platform.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/Platform.java
@@ -20,13 +20,38 @@
 
 /** Services that are needed to be provided by the platform during encoding. */
 public interface Platform {
+
+    /**
+     * Converts a platform-specific image object into a platform-independent byte buffer
+     *
+     * @param image
+     * @return
+     */
     @Nullable
     byte[] imageToByteArray(@NonNull Object image);
 
+    /**
+     * Returns the width of a platform-specific image object
+     *
+     * @param image platform-specific image object
+     * @return the width of the image in pixels
+     */
     int getImageWidth(@NonNull Object image);
 
+    /**
+     * Returns the height of a platform-specific image object
+     *
+     * @param image platform-specific image object
+     * @return the height of the image in pixels
+     */
     int getImageHeight(@NonNull Object image);
 
+    /**
+     * Converts a platform-specific path object into a platform-independent float buffer
+     *
+     * @param path
+     * @return
+     */
     @Nullable
     float[] pathToFloatArray(@NonNull Object path);
 
@@ -38,6 +63,12 @@
         TODO,
     }
 
+    /**
+     * Log a message
+     *
+     * @param category
+     * @param message
+     */
     void log(LogCategory category, String message);
 
     Platform None =
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
index fc1e36d..39cc997 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeBuffer.java
@@ -58,6 +58,8 @@
 import com.android.internal.widget.remotecompose.core.operations.MatrixTranslate;
 import com.android.internal.widget.remotecompose.core.operations.NamedVariable;
 import com.android.internal.widget.remotecompose.core.operations.PaintData;
+import com.android.internal.widget.remotecompose.core.operations.ParticlesCreate;
+import com.android.internal.widget.remotecompose.core.operations.ParticlesLoop;
 import com.android.internal.widget.remotecompose.core.operations.PathAppend;
 import com.android.internal.widget.remotecompose.core.operations.PathCreate;
 import com.android.internal.widget.remotecompose.core.operations.PathData;
@@ -77,6 +79,8 @@
 import com.android.internal.widget.remotecompose.core.operations.layout.CanvasContent;
 import com.android.internal.widget.remotecompose.core.operations.layout.ComponentStart;
 import com.android.internal.widget.remotecompose.core.operations.layout.ContainerEnd;
+import com.android.internal.widget.remotecompose.core.operations.layout.ImpulseOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.ImpulseProcess;
 import com.android.internal.widget.remotecompose.core.operations.layout.LayoutComponentContent;
 import com.android.internal.widget.remotecompose.core.operations.layout.LoopOperation;
 import com.android.internal.widget.remotecompose.core.operations.layout.RootLayoutComponent;
@@ -411,11 +415,7 @@
             BitmapData.apply(
                     mBuffer, imageId, imageWidth, imageHeight, data); // todo: potential npe
         }
-        int contentDescriptionId = 0;
-        if (contentDescription != null) {
-            contentDescriptionId = addText(contentDescription);
-        }
-        DrawBitmap.apply(mBuffer, imageId, left, top, right, bottom, contentDescriptionId);
+        addDrawBitmap(imageId, left, top, right, bottom, contentDescription);
     }
 
     /**
@@ -441,6 +441,24 @@
     }
 
     /**
+     * @param imageId The Id bitmap to be drawn
+     * @param left left coordinate of rectangle that the bitmap will be to fit into
+     * @param top top coordinate of rectangle that the bitmap will be to fit into
+     * @param contentDescription content description of the image
+     */
+    public void addDrawBitmap(
+            int imageId, float left, float top, @Nullable String contentDescription) {
+        int imageWidth = mPlatform.getImageWidth(imageId);
+        int imageHeight = mPlatform.getImageHeight(imageId);
+        int contentDescriptionId = 0;
+        if (contentDescription != null) {
+            contentDescriptionId = addText(contentDescription);
+        }
+        DrawBitmap.apply(
+                mBuffer, imageId, left, top, imageWidth, imageHeight, contentDescriptionId);
+    }
+
+    /**
      * @param image The bitmap to be drawn
      * @param srcLeft left coordinate in the source bitmap will be to extracted
      * @param srcTop top coordinate in the source bitmap will be to extracted
@@ -537,7 +555,7 @@
     }
 
     /**
-     * This defines the name of the color given the id.
+     * This defines the name of the bitmap given the id.
      *
      * @param id of the Bitmap
      * @param name Name of the color
@@ -2060,4 +2078,61 @@
     public int nextId() {
         return mRemoteComposeState.nextId();
     }
+
+    private boolean mInImpulseProcess = false;
+
+    /**
+     * add an impulse. (must be followed by impulse end)
+     *
+     * @param duration duration of the impulse
+     * @param start the start time
+     */
+    public void addImpulse(float duration, float start) {
+        ImpulseOperation.apply(mBuffer, duration, start);
+        mInImpulseProcess = false;
+    }
+
+    /** add an impulse process */
+    public void addImpulseProcess() {
+        ImpulseProcess.apply(mBuffer);
+        mInImpulseProcess = true;
+    }
+
+    /** Add an impulse end */
+    public void addImpulseEnd() {
+        ContainerEnd.apply(mBuffer);
+        if (mInImpulseProcess) {
+            ContainerEnd.apply(mBuffer);
+        }
+        mInImpulseProcess = false;
+    }
+
+    /**
+     * Start a particle engine container & initial setup
+     *
+     * @param id the particle engine id
+     * @param varIds list of variable ids
+     * @param initialExpressions the expressions used to initialize the variables
+     * @param particleCount the number of particles to draw
+     */
+    public void addParticles(
+            int id, int[] varIds, float[][] initialExpressions, int particleCount) {
+        ParticlesCreate.apply(mBuffer, id, varIds, initialExpressions, particleCount);
+    }
+
+    /**
+     * Setup the particle engine loop
+     *
+     * @param id the particle engine id
+     * @param restart value on restart
+     * @param expressions the expressions used to update the variables during the particles run
+     */
+    public void addParticlesLoop(int id, float[] restart, float[][] expressions) {
+        ParticlesLoop.apply(mBuffer, id, restart, expressions);
+    }
+
+    /** Closes the particle engine container */
+    public void addParticleLoopEnd() {
+        ContainerEnd.apply(mBuffer);
+    }
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
index cd26198..43f8ea7d 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteComposeState.java
@@ -528,6 +528,7 @@
 
     public void setContext(@NonNull RemoteContext context) {
         mRemoteContext = context;
+        mRemoteContext.clearLastOpCount();
     }
 
     public void updateObject(int id, @NonNull Object value) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
index 63469aa..23c3628 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/RemoteContext.java
@@ -40,12 +40,12 @@
  * <p>We also contain a PaintContext, so that any operation can draw as needed.
  */
 public abstract class RemoteContext {
-    private static final int MAX_OP_COUNT = 100_000; // Maximum cmds per frame
+    private static final int MAX_OP_COUNT = 20_000; // Maximum cmds per frame
     protected @NonNull CoreDocument mDocument =
             new CoreDocument(); // todo: is this a valid way to initialize? bbade@
     public @NonNull RemoteComposeState mRemoteComposeState =
             new RemoteComposeState(); // todo, is this a valid use of RemoteComposeState -- bbade@
-    long mStart = System.nanoTime(); // todo This should be set at a hi level
+
     @Nullable protected PaintContext mPaintContext = null;
     protected float mDensity = 2.75f;
 
@@ -71,6 +71,11 @@
         return mDensity;
     }
 
+    /**
+     * Set the density of the document
+     *
+     * @param density
+     */
     public void setDensity(float density) {
         if (density > 0) {
             mDensity = density;
@@ -142,7 +147,6 @@
      * @return a monotonic time in seconds (arbitrary zero point)
      */
     public float getAnimationTime() {
-        mAnimationTime = (System.nanoTime() - mStart) * 1E-9f; // Eliminate
         return mAnimationTime;
     }
 
@@ -243,6 +247,11 @@
 
     public abstract @Nullable Object getObject(int mId);
 
+    /**
+     * Add a touch listener to the context
+     *
+     * @param touchExpression
+     */
     public void addTouchListener(TouchListener touchExpression) {}
 
     /**
@@ -337,6 +346,16 @@
     // Operations
     ///////////////////////////////////////////////////////////////////////////////////////////////
 
+    /**
+     * Set the main information about a document
+     *
+     * @param majorVersion major version of the document protocol used
+     * @param minorVersion minor version of the document protocol used
+     * @param patchVersion patch version of the document protocol used
+     * @param width original width of the document when created
+     * @param height original height of the document when created
+     * @param capabilities bitmask of capabilities used in the document (TBD)
+     */
     public void header(
             int majorVersion,
             int minorVersion,
@@ -552,6 +571,15 @@
     /** Defines when the last build was made */
     public static final int ID_API_LEVEL = 28;
 
+    /** Defines when the TOUCH EVENT HAPPENED */
+    public static final int ID_TOUCH_EVENT_TIME = 29;
+
+    /** Animation time in seconds */
+    public static final int ID_ANIMATION_TIME = 30;
+
+    /** The delta between current and last Frame */
+    public static final int ID_ANIMATION_DELTA_TIME = 31;
+
     public static final float FLOAT_DENSITY = Utils.asNan(ID_DENSITY);
 
     /** CONTINUOUS_SEC is seconds from midnight looping every hour 0-3600 */
@@ -595,6 +623,15 @@
     /** TOUCH_VEL_Y is the x velocity of the touch */
     public static final float FLOAT_TOUCH_VEL_Y = Utils.asNan(ID_TOUCH_VEL_Y);
 
+    /** TOUCH_EVENT_TIME the time of the touch */
+    public static final float FLOAT_TOUCH_EVENT_TIME = Utils.asNan(ID_TOUCH_EVENT_TIME);
+
+    /** Animation time in seconds */
+    public static final float FLOAT_ANIMATION_TIME = Utils.asNan(ID_ANIMATION_TIME);
+
+    /** Animation time in seconds */
+    public static final float FLOAT_ANIMATION_DELTA_TIME = Utils.asNan(ID_ANIMATION_DELTA_TIME);
+
     /** X acceleration sensor value in M/s^2 */
     public static final float FLOAT_ACCELERATION_X = Utils.asNan(ID_ACCELERATION_X);
 
@@ -706,4 +743,9 @@
         mOpCount = 0;
         return count;
     }
+
+    /** Explicitly clear the operation counter */
+    public void clearLastOpCount() {
+        mOpCount = 0;
+    }
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java b/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java
index 79ac789..3789621 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/SerializableToString.java
@@ -20,5 +20,11 @@
 import com.android.internal.widget.remotecompose.core.operations.utilities.StringSerializer;
 
 public interface SerializableToString {
+    /**
+     * Returns a stable string representation of an operation
+     *
+     * @param indent the indentation for that operation
+     * @param serializer the serializer object
+     */
     void serializeToString(int indent, @NonNull StringSerializer serializer);
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java b/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java
index 611ba97..0a1be82 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/TouchListener.java
@@ -15,6 +15,8 @@
  */
 package com.android.internal.widget.remotecompose.core;
 
+import com.android.internal.widget.remotecompose.core.operations.layout.Component;
+
 /** Interface used by objects to register for touch events */
 public interface TouchListener {
     /**
@@ -45,4 +47,11 @@
      * @param y the y coord of the drag
      */
     void touchDrag(RemoteContext context, float x, float y);
+
+    /**
+     * Called after the touch event handler is inflated
+     *
+     * @param component component it is under
+     */
+    void setComponent(Component component);
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
index 0174ce5..0972e05 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentationBuilder.java
@@ -18,11 +18,33 @@
 import android.annotation.NonNull;
 
 public interface DocumentationBuilder {
+
+    /**
+     * Add arbitrary text to the documentation
+     *
+     * @param value
+     */
     void add(@NonNull String value);
 
+    /**
+     * Add the operation to the documentation
+     *
+     * @param category category of the operation
+     * @param id the OPCODE of the operation
+     * @param name the name of the operation
+     * @return a DocumentedOperation
+     */
     @NonNull
     DocumentedOperation operation(@NonNull String category, int id, @NonNull String name);
 
+    /**
+     * Add the operation to the documentation as a Work in Progress (WIP) operation
+     *
+     * @param category category of the operation
+     * @param id the OPCODE of the operation
+     * @param name the name of the operation
+     * @return a DocumentedOperation
+     */
     @NonNull
     DocumentedOperation wipOperation(@NonNull String category, int id, @NonNull String name);
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
index 2806a5e..487ea2e 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedCompanionOperation.java
@@ -18,5 +18,10 @@
 import android.annotation.NonNull;
 
 public interface DocumentedCompanionOperation {
+    /**
+     * A callback to populate the documentation of an operation
+     *
+     * @param doc the document being built
+     */
     void documentation(@NonNull DocumentationBuilder doc);
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
index bfab623..ffe8871 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/DocumentedOperation.java
@@ -49,6 +49,12 @@
     int mExamplesWidth = 100;
     int mExamplesHeight = 100;
 
+    /**
+     * Returns the string representation of a field type
+     *
+     * @param type
+     * @return
+     */
     @NonNull
     public static String getType(int type) {
         switch (type) {
@@ -117,6 +123,11 @@
         return mVarSize;
     }
 
+    /**
+     * Returns the size of the operation fields
+     *
+     * @return size in bytes
+     */
     public int getSizeFields() {
         int size = 0;
         mVarSize = "";
@@ -152,12 +163,29 @@
         return mExamplesHeight;
     }
 
+    /**
+     * Document a field of the operation
+     *
+     * @param type
+     * @param name
+     * @param description
+     * @return
+     */
     @NonNull
     public DocumentedOperation field(int type, @NonNull String name, @NonNull String description) {
         mFields.add(new OperationField(type, name, description));
         return this;
     }
 
+    /**
+     * Document a field of the operation
+     *
+     * @param type
+     * @param name
+     * @param varSize
+     * @param description
+     * @return
+     */
     @NonNull
     public DocumentedOperation field(
             int type, @NonNull String name, @NonNull String varSize, @NonNull String description) {
@@ -165,6 +193,13 @@
         return this;
     }
 
+    /**
+     * Add possible values for the operation field
+     *
+     * @param name
+     * @param value
+     * @return
+     */
     @NonNull
     public DocumentedOperation possibleValues(@NonNull String name, int value) {
         if (!mFields.isEmpty()) {
@@ -173,24 +208,50 @@
         return this;
     }
 
+    /**
+     * Add a description
+     *
+     * @param description
+     * @return
+     */
     @NonNull
     public DocumentedOperation description(@NonNull String description) {
         mDescription = description;
         return this;
     }
 
+    /**
+     * Add arbitrary text as examples
+     *
+     * @param examples
+     * @return
+     */
     @NonNull
     public DocumentedOperation examples(@NonNull String examples) {
         mTextExamples = examples;
         return this;
     }
 
+    /**
+     * Add an example image
+     *
+     * @param name the title of the image
+     * @param imagePath the path of the image
+     * @return
+     */
     @NonNull
     public DocumentedOperation exampleImage(@NonNull String name, @NonNull String imagePath) {
         mExamples.add(new StringPair(name, imagePath));
         return this;
     }
 
+    /**
+     * Add examples with a given size
+     *
+     * @param width
+     * @param height
+     * @return
+     */
     @NonNull
     public DocumentedOperation examplesDimension(int width, int height) {
         mExamplesWidth = width;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
index 9febcfe..e120f31 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/documentation/OperationField.java
@@ -61,10 +61,21 @@
         return mPossibleValues;
     }
 
+    /**
+     * Add possible values for a field
+     *
+     * @param name
+     * @param value
+     */
     public void possibleValue(@NonNull String name, @NonNull String value) {
         mPossibleValues.add(new StringPair(name, value));
     }
 
+    /**
+     * Return true if the field has enumerated values
+     *
+     * @return true if enumerated values, false otherwise
+     */
     public boolean hasEnumeratedValues() {
         return !mPossibleValues.isEmpty();
     }
@@ -74,6 +85,11 @@
         return mVarSize;
     }
 
+    /**
+     * Returns the size in byte of the field depending on its type, or -1 if unknown
+     *
+     * @return the size in bytes
+     */
     public int getSize() {
         switch (mType) {
             case DocumentedOperation.BYTE:
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
index 4c96025..98c2745 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Header.java
@@ -135,6 +135,15 @@
         return OP_CODE;
     }
 
+    /**
+     * Apply the header to the wire buffer
+     *
+     * @param buffer
+     * @param width
+     * @param height
+     * @param density
+     * @param capabilities
+     */
     public static void apply(
             @NonNull WireBuffer buffer, int width, int height, float density, long capabilities) {
         buffer.start(OP_CODE);
@@ -193,6 +202,11 @@
                 .field(LONG, "CAPABILITIES", "Major version");
     }
 
+    /**
+     * Set the version on a document
+     *
+     * @param document
+     */
     public void setVersion(CoreDocument document) {
         document.setVersion(mMajorVersion, mMinorVersion, mPatchVersion);
     }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java
new file mode 100644
index 0000000..9e891c4
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesCreate.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+import static com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression.VAR1;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This creates a particle system. which consist of id, particleCount, array of id's and equations
+ * for constructing the particles
+ */
+public class ParticlesCreate extends Operation implements VariableSupport {
+    private static final int OP_CODE = Operations.PARTICLE_CREATE;
+    private static final String CLASS_NAME = "ParticlesCreate";
+    private final int mId;
+    private final float[][] mEquations;
+    private final float[][] mOutEquations;
+    private final float[][] mParticles;
+    private final int[] mIndexeVars; // the elements in mEquations that INDEXES
+    private final int mParticleCount;
+    private final int[] mVarId;
+    private static final int MAX_FLOAT_ARRAY = 2000;
+    private static final int MAX_EQU_LENGTH = 32;
+    @NonNull AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+
+    public ParticlesCreate(int id, int[] varId, float[][] values, int particleCount) {
+        mId = id;
+        mVarId = varId;
+        mEquations = values;
+        mParticleCount = particleCount;
+        mOutEquations = new float[values.length][];
+        for (int i = 0; i < values.length; i++) {
+            mOutEquations[i] = new float[values[i].length];
+            System.arraycopy(values[i], 0, mOutEquations[i], 0, values[i].length);
+        }
+        mParticles = new float[particleCount][varId.length];
+
+        int[] index = new int[20];
+        int indexes = 0;
+        int var1Int = Float.floatToRawIntBits(VAR1);
+        for (int j = 0; j < mEquations.length; j++) {
+            for (int k = 0; k < mEquations[j].length; k++) {
+                if (Float.isNaN(mEquations[j][k])
+                        && Float.floatToRawIntBits(mEquations[j][k]) == var1Int) {
+                    index[indexes++] = j * mEquations.length + k;
+                }
+            }
+        }
+        mIndexeVars = Arrays.copyOf(index, indexes);
+    }
+
+    @Override
+    public void updateVariables(@NonNull RemoteContext context) {
+        for (int i = 0; i < mEquations.length; i++) {
+
+            for (int j = 0; j < mEquations[i].length; j++) {
+                float v = mEquations[i][j];
+                mOutEquations[i][j] =
+                        (Float.isNaN(v)
+                                        && !AnimatedFloatExpression.isMathOperator(v)
+                                        && !NanMap.isDataVariable(v))
+                                ? context.getFloat(Utils.idFromNan(v))
+                                : v;
+            }
+        }
+    }
+
+    @Override
+    public void registerListening(@NonNull RemoteContext context) {
+        context.putObject(mId, this); // T
+        for (int i = 0; i < mEquations.length; i++) {
+            float[] mEquation = mEquations[i];
+            for (float v : mEquation) {
+                if (Float.isNaN(v)
+                        && !AnimatedFloatExpression.isMathOperator(v)
+                        && !NanMap.isDataVariable(v)) {
+                    context.listensTo(Utils.idFromNan(v), this);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void write(@NonNull WireBuffer buffer) {
+        apply(buffer, mId, mVarId, mEquations, mParticleCount);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        String str = "ParticlesCreate[" + Utils.idString(mId) + "] ";
+        for (int j = 0; j < mVarId.length; j++) {
+            str += "[" + mVarId[j] + "] ";
+            float[] equation = mEquations[j];
+            String[] labels = new String[equation.length];
+            for (int i = 0; i < equation.length; i++) {
+                if (Float.isNaN(equation[i])) {
+                    labels[i] = "[" + Utils.idStringFromNan(equation[i]) + "]";
+                }
+            }
+            str += AnimatedFloatExpression.toString(equation, labels) + "\n";
+        }
+
+        return str;
+    }
+
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param id
+     * @param varId
+     * @param equations
+     * @param particleCount
+     */
+    public static void apply(
+            @NonNull WireBuffer buffer,
+            int id,
+            @NonNull int[] varId,
+            @NonNull float[][] equations,
+            int particleCount) {
+        buffer.start(OP_CODE);
+        buffer.writeInt(id);
+        buffer.writeInt(particleCount);
+        buffer.writeInt(varId.length);
+        for (int i = 0; i < varId.length; i++) {
+            buffer.writeInt(varId[i]);
+            buffer.writeInt(equations[i].length);
+            for (int j = 0; j < equations[i].length; j++) {
+                buffer.writeFloat(equations[i][j]);
+            }
+        }
+    }
+
+    /**
+     * Read this operation and add it to the list of operations
+     *
+     * @param buffer the buffer to read
+     * @param operations the list of operations that will be added to
+     */
+    public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+        int id = buffer.readInt();
+        int particleCount = buffer.readInt();
+        int varLen = buffer.readInt();
+        if (varLen > MAX_FLOAT_ARRAY) {
+            throw new RuntimeException(varLen + " map entries more than max = " + MAX_FLOAT_ARRAY);
+        }
+        int[] varId = new int[varLen];
+        float[][] equations = new float[varLen][];
+        for (int i = 0; i < varId.length; i++) {
+            varId[i] = buffer.readInt();
+            int equLen = buffer.readInt();
+            if (equLen > MAX_EQU_LENGTH) {
+                throw new RuntimeException(
+                        equLen + " map entries more than max = " + MAX_FLOAT_ARRAY);
+            }
+            equations[i] = new float[equLen];
+            for (int j = 0; j < equations[i].length; j++) {
+                equations[i][j] = buffer.readFloat();
+            }
+        }
+        ParticlesCreate data = new ParticlesCreate(id, varId, equations, particleCount);
+        operations.add(data);
+    }
+
+    /**
+     * Populate the documentation with a description of this operation
+     *
+     * @param doc to append the description to.
+     */
+    public static void documentation(@NonNull DocumentationBuilder doc) {
+        doc.operation("Data Operations", OP_CODE, CLASS_NAME)
+                .description("Creates a particle system")
+                .field(DocumentedOperation.INT, "id", "The reference of the particle system")
+                .field(INT, "particleCount", "number of particles to create")
+                .field(INT, "varLen", "number of variables asociate with the particles")
+                .field(FLOAT_ARRAY, "id", "varLen", "id followed by equations")
+                .field(INT, "equLen", "length of the equation")
+                .field(FLOAT_ARRAY, "equation", "varLen * equLen", "float array equations");
+    }
+
+    @NonNull
+    @Override
+    public String deepToString(@NonNull String indent) {
+        return indent + toString();
+    }
+
+    void initializeParticle(int pNo) {
+        for (int j = 0; j < mParticles[pNo].length; j++) {
+            for (int k = 0; k < mIndexeVars.length; k++) {
+                int pos = mIndexeVars[k];
+                int jIndex = pos / mOutEquations.length;
+                int kIndex = pos % mOutEquations.length;
+                mOutEquations[jIndex][kIndex] = pNo;
+            }
+            mParticles[pNo][j] = mExp.eval(mOutEquations[j], mOutEquations[j].length);
+        }
+    }
+
+    @Override
+    public void apply(@NonNull RemoteContext context) {
+        for (int i = 0; i < mParticles.length; i++) {
+            initializeParticle(i);
+        }
+    }
+
+    public float[][] getParticles() {
+        return mParticles;
+    }
+
+    public int[] getVariableIds() {
+        return mVarId;
+    }
+
+    public float[][] getEquations() {
+        return mOutEquations;
+    }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java
new file mode 100644
index 0000000..7910790
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/ParticlesLoop.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations;
+
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.FLOAT_ARRAY;
+import static com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation.INT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+import com.android.internal.widget.remotecompose.core.operations.layout.Container;
+import com.android.internal.widget.remotecompose.core.operations.utilities.AnimatedFloatExpression;
+import com.android.internal.widget.remotecompose.core.operations.utilities.NanMap;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This provides the mechinism to evolve the particles It consist of a restart equation and a list
+ * of equations particle restarts if restart equation > 0
+ */
+public class ParticlesLoop extends PaintOperation implements VariableSupport, Container {
+    private static final int OP_CODE = Operations.PARTICLE_LOOP;
+    private static final String CLASS_NAME = "ParticlesLoop";
+    private final int mId;
+    private final float[] mRestart;
+    private final float[] mOutRestart;
+    private final float[][] mEquations;
+    private final float[][] mOutEquations;
+    private int[] mVarId;
+    private float[][] mParticles;
+    private static final int MAX_FLOAT_ARRAY = 2000;
+    private static final int MAX_EQU_LENGTH = 32;
+    ParticlesCreate mParticlesSource;
+
+    @NonNull
+    @Override
+    public ArrayList<Operation> getList() {
+        return mList;
+    }
+
+    @NonNull private ArrayList<Operation> mList = new ArrayList<>();
+
+    @NonNull AnimatedFloatExpression mExp = new AnimatedFloatExpression();
+
+    /**
+     * Create a new ParticlesLoop operation
+     *
+     * @param id of the create
+     * @param restart the restart equation kills and restart when positive
+     * @param values the loop equations
+     */
+    public ParticlesLoop(int id, float[] restart, float[][] values) {
+        mId = id;
+        mRestart = restart;
+        if (restart != null) {
+            mOutRestart = new float[restart.length];
+            System.arraycopy(restart, 0, mOutRestart, 0, restart.length);
+        } else {
+            mOutRestart = null;
+        }
+
+        mEquations = values;
+        mOutEquations = new float[values.length][];
+        for (int i = 0; i < values.length; i++) {
+            mOutEquations[i] = new float[values[i].length];
+            System.arraycopy(values[i], 0, mOutEquations[i], 0, values[i].length);
+        }
+    }
+
+    @Override
+    public void updateVariables(@NonNull RemoteContext context) {
+        if (mOutRestart != null) {
+            for (int i = 0; i < mRestart.length; i++) {
+                float v = mRestart[i];
+                mOutRestart[i] =
+                        (Float.isNaN(v)
+                                        && !AnimatedFloatExpression.isMathOperator(v)
+                                        && !NanMap.isDataVariable(v))
+                                ? context.getFloat(Utils.idFromNan(v))
+                                : v;
+            }
+        }
+        for (int i = 0; i < mEquations.length; i++) {
+            float[] mEquation = mEquations[i];
+            for (int j = 0; j < mEquation.length; j++) {
+                float v = mEquation[j];
+                mOutEquations[i][j] =
+                        (Float.isNaN(v)
+                                        && !AnimatedFloatExpression.isMathOperator(v)
+                                        && !NanMap.isDataVariable(v))
+                                ? context.getFloat(Utils.idFromNan(v))
+                                : v;
+            }
+        }
+    }
+
+    @Override
+    public void registerListening(@NonNull RemoteContext context) {
+        mParticlesSource = (ParticlesCreate) context.getObject(mId);
+        mParticles = mParticlesSource.getParticles();
+        mVarId = mParticlesSource.getVariableIds();
+        if (mRestart != null) {
+            for (int i = 0; i < mRestart.length; i++) {
+                float v = mRestart[i];
+                if (Float.isNaN(v)
+                        && !AnimatedFloatExpression.isMathOperator(v)
+                        && !NanMap.isDataVariable(v)) {
+                    context.listensTo(Utils.idFromNan(v), this);
+                }
+            }
+        }
+        for (int i = 0; i < mEquations.length; i++) {
+            float[] mEquation = mEquations[i];
+            for (float v : mEquation) {
+                if (Float.isNaN(v)
+                        && !AnimatedFloatExpression.isMathOperator(v)
+                        && !NanMap.isDataVariable(v)) {
+                    context.listensTo(Utils.idFromNan(v), this);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void write(@NonNull WireBuffer buffer) {
+        apply(buffer, mId, mRestart, mEquations);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        String str = "ParticlesLoop[" + Utils.idString(mId) + "] ";
+        return str;
+    }
+
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param id
+     * @param restart
+     * @param equations
+     */
+    public static void apply(
+            @NonNull WireBuffer buffer,
+            int id,
+            @Nullable float[] restart,
+            @NonNull float[][] equations) {
+        buffer.start(OP_CODE);
+        buffer.writeInt(id);
+        if (restart != null) {
+            buffer.writeInt(restart.length);
+            for (int i = 0; i < restart.length; i++) {
+                buffer.writeFloat(restart[i]);
+            }
+        } else {
+            buffer.writeInt(0);
+        }
+        buffer.writeInt(equations.length);
+        for (int i = 0; i < equations.length; i++) {
+            buffer.writeInt(equations[i].length);
+            for (int j = 0; j < equations[i].length; j++) {
+                buffer.writeFloat(equations[i][j]);
+            }
+        }
+    }
+
+    /**
+     * Read this operation and add it to the list of operations
+     *
+     * @param buffer the buffer to read
+     * @param operations the list of operations that will be added to
+     */
+    public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+        int id = buffer.readInt();
+        int restartLen = buffer.readInt();
+        float[] restart = null;
+        if (restartLen > 0) {
+            restart = new float[restartLen];
+            for (int i = 0; i < restartLen; i++) {
+                restart[i] = buffer.readFloat();
+            }
+        }
+
+        int varLen = buffer.readInt();
+        if (varLen > MAX_FLOAT_ARRAY) {
+            throw new RuntimeException(varLen + " map entries more than max = " + MAX_FLOAT_ARRAY);
+        }
+
+        float[][] equations = new float[varLen][];
+        for (int i = 0; i < varLen; i++) {
+
+            int equLen = buffer.readInt();
+            if (equLen > MAX_EQU_LENGTH) {
+                throw new RuntimeException(
+                        equLen + " map entries more than max = " + MAX_FLOAT_ARRAY);
+            }
+            equations[i] = new float[equLen];
+            for (int j = 0; j < equations[i].length; j++) {
+                equations[i][j] = buffer.readFloat();
+            }
+        }
+        ParticlesLoop data = new ParticlesLoop(id, restart, equations);
+        operations.add(data);
+    }
+
+    /**
+     * Populate the documentation with a description of this operation
+     *
+     * @param doc to append the description to.
+     */
+    public static void documentation(@NonNull DocumentationBuilder doc) {
+        doc.operation("Data Operations", OP_CODE, CLASS_NAME)
+                .description("This evolves the particles & recycles them")
+                .field(DocumentedOperation.INT, "id", "id of particle system")
+                .field(
+                        INT,
+                        "recycleLen",
+                        "the number of floats in restart equeation if 0 no restart")
+                .field(FLOAT_ARRAY, "values", "recycleLen", "array of floats")
+                .field(INT, "varLen", "the number of equations to follow")
+                .field(INT, "equLen", "the number of equations to follow")
+                .field(FLOAT_ARRAY, "values", "equLen", "floats for the equation");
+    }
+
+    @NonNull
+    @Override
+    public String deepToString(@NonNull String indent) {
+        return indent + toString();
+    }
+
+    @Override
+    public void paint(@NonNull PaintContext context) {
+        RemoteContext remoteContext = context.getContext();
+        for (int i = 0; i < mParticles.length; i++) {
+            // Save the values to context TODO hand code the update
+            for (int j = 0; j < mParticles[i].length; j++) {
+                remoteContext.loadFloat(mVarId[j], mParticles[i][j]);
+                updateVariables(remoteContext);
+            }
+            // Evaluate the update function
+            for (int j = 0; j < mParticles[i].length; j++) {
+                mParticles[i][j] = mExp.eval(mOutEquations[j], mOutEquations[j].length);
+                remoteContext.loadFloat(mVarId[j], mParticles[i][j]);
+            }
+            // test for reset
+            if (mOutRestart != null) {
+                for (int k = 0; k < mRestart.length; k++) {
+                    float v = mRestart[k];
+                    mOutRestart[k] =
+                            (Float.isNaN(v)
+                                            && !AnimatedFloatExpression.isMathOperator(v)
+                                            && !NanMap.isDataVariable(v))
+                                    ? remoteContext.getFloat(Utils.idFromNan(v))
+                                    : v;
+                }
+                if (mExp.eval(mOutRestart, mOutRestart.length) > 0) {
+                    mParticlesSource.initializeParticle(i);
+                }
+            }
+
+            for (Operation op : mList) {
+                if (op instanceof VariableSupport) {
+                    ((VariableSupport) op).updateVariables(context.getContext());
+                }
+
+                remoteContext.incrementOpCount();
+                op.apply(context.getContext());
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
index 55dd882..129201c 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentBehavior.java
@@ -219,6 +219,15 @@
         return OP_CODE;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param scroll
+     * @param alignment
+     * @param sizing
+     * @param mode
+     */
     public static void apply(
             @NonNull WireBuffer buffer, int scroll, int alignment, int sizing, int mode) {
         buffer.start(OP_CODE);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
index ad86e0f..c1ddf63 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/RootContentDescription.java
@@ -95,6 +95,12 @@
         return OP_CODE;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param contentDescription
+     */
     public static void apply(@NonNull WireBuffer buffer, int contentDescription) {
         buffer.start(Operations.ROOT_CONTENT_DESCRIPTION);
         buffer.writeInt(contentDescription);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
index e9aae1e..1698ecb 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/Theme.java
@@ -92,6 +92,12 @@
         return OP_CODE;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param theme
+     */
     public static void apply(@NonNull WireBuffer buffer, int theme) {
         buffer.start(OP_CODE);
         buffer.writeInt(theme);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java
index 3b293bd..9976281 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/TouchExpression.java
@@ -368,6 +368,7 @@
      *
      * @param component the component, or null if outside
      */
+    @Override
     public void setComponent(@Nullable Component component) {
         mComponent = component;
         if (mComponent != null) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
index 511858aa..abb7ad8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/CanvasContent.java
@@ -66,6 +66,12 @@
         return "CANVAS_CONTENT";
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param componentId
+     */
     public static void apply(@NonNull WireBuffer buffer, int componentId) {
         buffer.start(Operations.LAYOUT_CANVAS_CONTENT);
         buffer.writeInt(componentId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
index 5f084e9..110bd30 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ClickModifierOperation.java
@@ -77,6 +77,12 @@
         return CoreSemantics.Mode.MERGE;
     }
 
+    /**
+     * Animate ripple
+     *
+     * @param x starting position x of the ripple
+     * @param y starting position y of the ripple
+     */
     public void animateRipple(float x, float y) {
         mAnimateRippleStart = System.currentTimeMillis();
         mAnimateRippleX = x;
@@ -212,6 +218,11 @@
         return "ClickModifier";
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     */
     public static void apply(@NonNull WireBuffer buffer) {
         buffer.start(OP_CODE);
     }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
index eee2aab..8e733ce 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Component.java
@@ -24,6 +24,7 @@
 import com.android.internal.widget.remotecompose.core.PaintOperation;
 import com.android.internal.widget.remotecompose.core.RemoteContext;
 import com.android.internal.widget.remotecompose.core.SerializableToString;
+import com.android.internal.widget.remotecompose.core.TouchListener;
 import com.android.internal.widget.remotecompose.core.VariableSupport;
 import com.android.internal.widget.remotecompose.core.WireBuffer;
 import com.android.internal.widget.remotecompose.core.operations.ComponentValue;
@@ -236,6 +237,7 @@
         finalizeCreation();
     }
 
+    /** Callback on component creation TODO: replace with inflate() */
     public void finalizeCreation() {
         for (Operation op : mList) {
             if (op instanceof Component) {
@@ -273,6 +275,11 @@
         context.mLastComponent = prev;
     }
 
+    /**
+     * Add a component value to the component
+     *
+     * @param v
+     */
     public void addComponentValue(@NonNull ComponentValue v) {
         mComponentValues.add(v);
     }
@@ -303,10 +310,10 @@
      */
     public void inflate() {
         for (Operation op : mList) {
-            if (op instanceof TouchExpression) {
+            if (op instanceof TouchListener) {
                 // Make sure to set the component of a touch expression that belongs to us!
-                TouchExpression touchExpression = (TouchExpression) op;
-                touchExpression.setComponent(this);
+                TouchListener touchListener = (TouchListener) op;
+                touchListener.setComponent(this);
             }
         }
     }
@@ -317,6 +324,11 @@
         INVISIBLE
     }
 
+    /**
+     * Returns true if the component is visible
+     *
+     * @return
+     */
     public boolean isVisible() {
         if (mVisibility != Visibility.VISIBLE || mParent == null) {
             return mVisibility == Visibility.VISIBLE;
@@ -327,6 +339,11 @@
         return true;
     }
 
+    /**
+     * Set the visibility of the component
+     *
+     * @param visibility can be VISIBLE, INVISIBLE or GONE
+     */
     public void setVisibility(@NonNull Visibility visibility) {
         if (visibility != mVisibility || visibility != mScheduledVisibility) {
             mScheduledVisibility = visibility;
@@ -443,6 +460,13 @@
 
     @NonNull public float[] locationInWindow = new float[2];
 
+    /**
+     * Hit detection -- returns true if the point (x, y) is inside the component
+     *
+     * @param x
+     * @param y
+     * @return
+     */
     public boolean contains(float x, float y) {
         locationInWindow[0] = 0f;
         locationInWindow[1] = 0f;
@@ -454,14 +478,32 @@
         return x >= lx1 && x < lx2 && y >= ly1 && y < ly2;
     }
 
+    /**
+     * Returns the horizontal scroll value of the content of this component
+     *
+     * @return 0 if no scroll
+     */
     public float getScrollX() {
         return 0;
     }
 
+    /**
+     * Returns the vertical scroll value of the content of this component
+     *
+     * @return 0 if no scroll
+     */
     public float getScrollY() {
         return 0;
     }
 
+    /**
+     * Click handler
+     *
+     * @param context
+     * @param document
+     * @param x
+     * @param y
+     */
     public void onClick(
             @NonNull RemoteContext context, @NonNull CoreDocument document, float x, float y) {
         if (!contains(x, y)) {
@@ -479,6 +521,14 @@
         }
     }
 
+    /**
+     * Touch down handler
+     *
+     * @param context
+     * @param document
+     * @param x
+     * @param y
+     */
     public void onTouchDown(RemoteContext context, CoreDocument document, float x, float y) {
         if (!contains(x, y)) {
             return;
@@ -501,6 +551,17 @@
         }
     }
 
+    /**
+     * Touch Up handler
+     *
+     * @param context
+     * @param document
+     * @param x
+     * @param y
+     * @param dx
+     * @param dy
+     * @param force
+     */
     public void onTouchUp(
             RemoteContext context,
             CoreDocument document,
@@ -529,6 +590,15 @@
         }
     }
 
+    /**
+     * Touch Cancel handler
+     *
+     * @param context
+     * @param document
+     * @param x
+     * @param y
+     * @param force
+     */
     public void onTouchCancel(
             RemoteContext context, CoreDocument document, float x, float y, boolean force) {
         if (!force && !contains(x, y)) {
@@ -551,6 +621,15 @@
         }
     }
 
+    /**
+     * Touch Drag handler
+     *
+     * @param context
+     * @param document
+     * @param x
+     * @param y
+     * @param force
+     */
     public void onTouchDrag(
             RemoteContext context, CoreDocument document, float x, float y, boolean force) {
         if (!force && !contains(x, y)) {
@@ -573,6 +652,12 @@
         }
     }
 
+    /**
+     * Returns the location of the component relative to the root component
+     *
+     * @param value a 2 dimension float array that will receive the horizontal and vertical position
+     *     of the component.
+     */
     public void getLocationInWindow(@NonNull float[] value) {
         value[0] += mX;
         value[1] += mY;
@@ -681,6 +766,7 @@
         }
     }
 
+    /** Mark the tree as needing a repaint */
     public void needsRepaint() {
         try {
             getRoot().mNeedsRepaint = true;
@@ -689,6 +775,11 @@
         }
     }
 
+    /**
+     * Debugging function returning the list of child operations
+     *
+     * @return a formatted string with the list of operations
+     */
     @NonNull
     public String content() {
         StringBuilder builder = new StringBuilder();
@@ -700,6 +791,11 @@
         return builder.toString();
     }
 
+    /**
+     * Returns a string containing the text operations if any
+     *
+     * @return
+     */
     @NonNull
     public String textContent() {
         StringBuilder builder = new StringBuilder();
@@ -713,6 +809,12 @@
         return builder.toString();
     }
 
+    /**
+     * Utility debug function
+     *
+     * @param component
+     * @param context
+     */
     public void debugBox(@NonNull Component component, @NonNull PaintContext context) {
         float width = component.mWidth;
         float height = component.mHeight;
@@ -731,11 +833,22 @@
         context.restorePaint();
     }
 
+    /**
+     * Set the position of this component relative to its parent
+     *
+     * @param x horizontal position
+     * @param y vertical position
+     */
     public void setLayoutPosition(float x, float y) {
         this.mX = x;
         this.mY = y;
     }
 
+    /**
+     * The vertical position of this component relative to its parent
+     *
+     * @return
+     */
     public float getTranslateX() {
         if (mParent != null) {
             return mX - mParent.mX;
@@ -743,6 +856,11 @@
         return 0f;
     }
 
+    /**
+     * The horizontal position of this component relative to its parent
+     *
+     * @return
+     */
     public float getTranslateY() {
         if (mParent != null) {
             return mY - mParent.mY;
@@ -750,6 +868,11 @@
         return 0f;
     }
 
+    /**
+     * Paint the component itself.
+     *
+     * @param context
+     */
     public void paintingComponent(@NonNull PaintContext context) {
         if (mPreTranslate != null) {
             mPreTranslate.paint(context);
@@ -778,6 +901,12 @@
         context.getContext().mLastComponent = prev;
     }
 
+    /**
+     * If animation is turned on and we need to be animated, we'll apply it.
+     *
+     * @param context
+     * @return
+     */
     public boolean applyAnimationAsNeeded(@NonNull PaintContext context) {
         if (context.isAnimationEnabled() && mAnimateMeasure != null) {
             mAnimateMeasure.paint(context);
@@ -822,6 +951,11 @@
         paintingComponent(context);
     }
 
+    /**
+     * Extract child components
+     *
+     * @param components an ArrayList that will be populated by child components (if any)
+     */
     public void getComponents(@NonNull ArrayList<Component> components) {
         for (Operation op : mList) {
             if (op instanceof Component) {
@@ -830,6 +964,11 @@
         }
     }
 
+    /**
+     * Extract child TextData elements
+     *
+     * @param data an ArrayList that will be populated with the TextData elements (if any)
+     */
     public void getData(@NonNull ArrayList<TextData> data) {
         for (Operation op : mList) {
             if (op instanceof TextData) {
@@ -838,6 +977,11 @@
         }
     }
 
+    /**
+     * Returns the number of children components
+     *
+     * @return
+     */
     public int getComponentCount() {
         int count = 0;
         for (Operation op : mList) {
@@ -848,6 +992,12 @@
         return count;
     }
 
+    /**
+     * Return the id used for painting the component -- either its component id or its animation id
+     * (if set)
+     *
+     * @return
+     */
     public int getPaintId() {
         if (mAnimationId != -1) {
             return mAnimationId;
@@ -855,10 +1005,21 @@
         return mComponentId;
     }
 
+    /**
+     * Return true if the needsRepaint flag is set on this component
+     *
+     * @return
+     */
     public boolean doesNeedsRepaint() {
         return mNeedsRepaint;
     }
 
+    /**
+     * Utility function to return a component from its id
+     *
+     * @param cid
+     * @return
+     */
     @Nullable
     public Component getComponent(int cid) {
         if (mComponentId == cid || mAnimationId == cid) {
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
index f009d88..5ef71d0 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ComponentStart.java
@@ -126,6 +126,12 @@
     public static final int LAYOUT_ROW = 15;
     public static final int LAYOUT_COLUMN = 16;
 
+    /**
+     * Returns the string representation of the component type
+     *
+     * @param type
+     * @return a string representing the component type
+     */
     @NonNull
     public static String typeDescription(int type) {
         switch (type) {
@@ -179,6 +185,15 @@
         return Operations.COMPONENT_START;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param type
+     * @param componentId
+     * @param width
+     * @param height
+     */
     public static void apply(
             @NonNull WireBuffer buffer, int type, int componentId, float width, float height) {
         buffer.start(Operations.COMPONENT_START);
@@ -188,6 +203,11 @@
         buffer.writeFloat(height);
     }
 
+    /**
+     * Return the size of the operation in byte
+     *
+     * @return the size in byte
+     */
     public static int size() {
         return 1 + 4 + 4 + 4;
     }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Container.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Container.java
index c678f6c..41e2bf8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Container.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/Container.java
@@ -21,7 +21,13 @@
 
 import java.util.ArrayList;
 
+/** An Operation container */
 public interface Container {
+    /**
+     * Returns a list of child operations
+     *
+     * @return a list of child operations
+     */
     @NonNull
     ArrayList<Operation> getList();
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ContainerEnd.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ContainerEnd.java
index 4290c4b..004f194 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ContainerEnd.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ContainerEnd.java
@@ -68,6 +68,11 @@
         return Operations.CONTAINER_END;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     */
     public static void apply(@NonNull WireBuffer buffer) {
         buffer.start(id());
     }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java
new file mode 100644
index 0000000..e277d49
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseOperation.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
+import com.android.internal.widget.remotecompose.core.operations.Utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a Impulse Event To trigger an impulse event. set the startAt time to the
+ * context.getAnimationTime() Impluse Operation. This operation execute a list of actions once and
+ * the impluseProcess is executed for a fixed duration
+ */
+public class ImpulseOperation extends PaintOperation implements VariableSupport, Container {
+    private static final int OP_CODE = Operations.IMPULSE_START;
+    private static final String CLASS_NAME = "ImpulseOperation";
+    private float mDuration;
+    private float mStartAt;
+    private float mOutDuration;
+    private float mOutStartAt;
+    private boolean mInitialPass = true;
+    @NonNull public ArrayList<Operation> mList = new ArrayList<>();
+
+    int mIndexVariableId;
+
+    private ImpulseProcess mProcess;
+
+    /**
+     * Constructor for a Impulse Operation
+     *
+     * @param duration the duration of the impluse
+     * @param startAt the start time of the impluse
+     */
+    public ImpulseOperation(float duration, float startAt) {
+        mDuration = duration;
+        mStartAt = startAt;
+        mOutStartAt = startAt;
+        mOutDuration = duration;
+    }
+
+    @Override
+    public void registerListening(RemoteContext context) {
+        if (mProcess == null) {
+            System.out.println(".....");
+            Operation last = mList.get(mList.size() - 1);
+            if (last instanceof ImpulseProcess) {
+                mProcess = (ImpulseProcess) last;
+                mList.remove(last);
+            }
+        }
+        if (Float.isNaN(mStartAt)) {
+            context.listensTo(Utils.idFromNan(mStartAt), this);
+        }
+        if (Float.isNaN(mDuration)) {
+            context.listensTo(Utils.idFromNan(mDuration), this);
+        }
+        for (Operation operation : mList) {
+            if (operation instanceof VariableSupport) {
+                VariableSupport variableSupport = (VariableSupport) operation;
+                variableSupport.registerListening(context);
+            }
+        }
+        if (mProcess != null) {
+            mProcess.registerListening(context);
+        }
+    }
+
+    @Override
+    public void updateVariables(RemoteContext context) {
+
+        mOutDuration =
+                Float.isNaN(mDuration) ? context.getFloat(Utils.idFromNan(mDuration)) : mDuration;
+
+        mOutStartAt =
+                Float.isNaN(mStartAt) ? context.getFloat(Utils.idFromNan(mStartAt)) : mStartAt;
+        if (mProcess != null) {
+            mProcess.updateVariables(context);
+        }
+    }
+
+    @NonNull
+    public ArrayList<Operation> getList() {
+        return mList;
+    }
+
+    @Override
+    public void write(@NonNull WireBuffer buffer) {
+        apply(buffer, mDuration, mStartAt);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("LoopOperation\n");
+        for (Operation operation : mList) {
+            builder.append("  startAt: ");
+            builder.append(mStartAt);
+            builder.append(" duration: ");
+            builder.append(mDuration);
+            builder.append("\n");
+        }
+        return builder.toString();
+    }
+
+    @NonNull
+    @Override
+    public String deepToString(@NonNull String indent) {
+        return (indent != null ? indent : "") + toString();
+    }
+
+    @Override
+    public void paint(@NonNull PaintContext context) {
+        RemoteContext remoteContext = context.getContext();
+
+        if (remoteContext.getAnimationTime() < mOutStartAt + mOutDuration) {
+            if (mInitialPass) {
+                for (Operation op : mList) {
+                    if (op instanceof VariableSupport && op.isDirty()) {
+                        ((VariableSupport) op).updateVariables(context.getContext());
+                    }
+                    remoteContext.incrementOpCount();
+                    op.apply(context.getContext());
+                }
+                mInitialPass = false;
+            } else {
+                remoteContext.incrementOpCount();
+                if (mProcess != null) {
+                    mProcess.paint(context);
+                }
+            }
+        } else {
+            mInitialPass = true;
+        }
+    }
+
+    /**
+     * The name of the class
+     *
+     * @return the name
+     */
+    @NonNull
+    public static String name() {
+        return CLASS_NAME;
+    }
+
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param duration
+     * @param startAt
+     */
+    public static void apply(@NonNull WireBuffer buffer, float duration, float startAt) {
+        buffer.start(OP_CODE);
+        buffer.writeFloat(duration);
+        buffer.writeFloat(startAt);
+    }
+
+    /**
+     * Read this operation and add it to the list of operations
+     *
+     * @param buffer the buffer to read
+     * @param operations the list of operations that will be added to
+     */
+    public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+        float duration = buffer.readFloat();
+        float startAt = buffer.readFloat();
+
+        operations.add(new ImpulseOperation(duration, startAt));
+    }
+
+    /**
+     * Populate the documentation with a description of this operation
+     *
+     * @param doc to append the description to.
+     */
+    public static void documentation(@NonNull DocumentationBuilder doc) {
+        doc.operation("Operations", OP_CODE, name())
+                .description(
+                        "Impulse Operation. This operation execute a list of action for a fixed"
+                                + " duration")
+                .field(DocumentedOperation.FLOAT, "duration", "How long to last")
+                .field(DocumentedOperation.FLOAT, "startAt", "value step");
+    }
+
+    /**
+     * Calculate and estimate of the number of iterations
+     *
+     * @return number of loops or 10 if based on variables
+     */
+    public int estimateIterations() {
+        if (Float.isNaN(mDuration)) {
+            return 10; // this is a generic estmate if the values are variables;
+        }
+        return (int) (mDuration * 60);
+    }
+
+    /**
+     * set the impulse process. This gets executed for the duration of the impulse
+     *
+     * @param impulseProcess process to be executed every time
+     */
+    public void setProcess(ImpulseProcess impulseProcess) {
+        mProcess = impulseProcess;
+    }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java
new file mode 100644
index 0000000..f896f3d
--- /dev/null
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ImpulseProcess.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.widget.remotecompose.core.operations.layout;
+
+import android.annotation.NonNull;
+
+import com.android.internal.widget.remotecompose.core.Operation;
+import com.android.internal.widget.remotecompose.core.Operations;
+import com.android.internal.widget.remotecompose.core.PaintContext;
+import com.android.internal.widget.remotecompose.core.PaintOperation;
+import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.VariableSupport;
+import com.android.internal.widget.remotecompose.core.WireBuffer;
+import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Represents the repeating part of an Impulse. */
+public class ImpulseProcess extends PaintOperation implements VariableSupport, Container {
+    private static final int OP_CODE = Operations.IMPULSE_PROCESS;
+    private static final String CLASS_NAME = "ImpulseProcess";
+
+    @NonNull public ArrayList<Operation> mList = new ArrayList<>();
+
+    /** The constructor */
+    public ImpulseProcess() {}
+
+    @Override
+    public void registerListening(RemoteContext context) {
+        for (Operation operation : mList) {
+            if (operation instanceof VariableSupport) {
+                VariableSupport variableSupport = (VariableSupport) operation;
+                variableSupport.registerListening(context);
+            }
+        }
+    }
+
+    @Override
+    public void updateVariables(RemoteContext context) {
+        for (Operation operation : mList) {
+            if (operation instanceof VariableSupport) {
+                VariableSupport variableSupport = (VariableSupport) operation;
+                variableSupport.updateVariables(context);
+            }
+        }
+    }
+
+    /**
+     * The returns a list to be filled
+     *
+     * @return list to be filled
+     */
+    @NonNull
+    public ArrayList<Operation> getList() {
+        return mList;
+    }
+
+    @Override
+    public void write(@NonNull WireBuffer buffer) {
+        apply(buffer);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder(CLASS_NAME + "\n");
+        for (Operation operation : mList) {
+            builder.append("  ");
+            builder.append(operation);
+            builder.append("\n");
+        }
+        return builder.toString();
+    }
+
+    @NonNull
+    @Override
+    public String deepToString(@NonNull String indent) {
+        return (indent != null ? indent : "") + toString();
+    }
+
+    @Override
+    public void paint(@NonNull PaintContext context) {
+        RemoteContext remoteContext = context.getContext();
+        for (Operation op : mList) {
+            if (op instanceof VariableSupport && op.isDirty()) {
+                ((VariableSupport) op).updateVariables(context.getContext());
+            }
+            remoteContext.incrementOpCount();
+            op.apply(context.getContext());
+        }
+    }
+
+    /**
+     * The name of the class
+     *
+     * @return the name
+     */
+    @NonNull
+    public static String name() {
+        return "Loop";
+    }
+
+    /**
+     * Apply this operation to the buffer
+     *
+     * @param buffer
+     */
+    public static void apply(@NonNull WireBuffer buffer) {
+        buffer.start(OP_CODE);
+    }
+
+    /**
+     * Read this operation and add it to the list of operations
+     *
+     * @param buffer the buffer to read
+     * @param operations the list of operations that will be added to
+     */
+    public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
+        operations.add(new ImpulseProcess());
+    }
+
+    /**
+     * Populate the documentation with a description of this operation
+     *
+     * @param doc to append the description to.
+     */
+    public static void documentation(@NonNull DocumentationBuilder doc) {
+        doc.operation("Operations", OP_CODE, name())
+                .description("Impulse Process that runs a list of operations");
+    }
+
+    /**
+     * Calculate and estimate of the number of iterations
+     *
+     * @return number of loops or 10 if based on variables
+     */
+    public int estimateIterations() {
+        return 1;
+    }
+}
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
index 9103885..e71cb9a 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponent.java
@@ -22,6 +22,7 @@
 import com.android.internal.widget.remotecompose.core.OperationInterface;
 import com.android.internal.widget.remotecompose.core.PaintContext;
 import com.android.internal.widget.remotecompose.core.RemoteContext;
+import com.android.internal.widget.remotecompose.core.TouchListener;
 import com.android.internal.widget.remotecompose.core.VariableSupport;
 import com.android.internal.widget.remotecompose.core.operations.BitmapData;
 import com.android.internal.widget.remotecompose.core.operations.FloatExpression;
@@ -176,8 +177,8 @@
                     || (op instanceof PaintData)
                     || (op instanceof FloatExpression)) {
                 supportedOperations.add(op);
-                if (op instanceof TouchExpression) {
-                    ((TouchExpression) op).setComponent(this);
+                if (op instanceof TouchListener) {
+                    ((TouchListener) op).setComponent(this);
                 }
             } else {
                 // nothing
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
index 27172aa..4babe5f 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LayoutComponentContent.java
@@ -66,6 +66,12 @@
         return "CONTENT";
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param componentId
+     */
     public static void apply(@NonNull WireBuffer buffer, int componentId) {
         buffer.start(Operations.LAYOUT_CONTENT);
         buffer.writeInt(componentId);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java
index 6dce6f1..bfa417e8 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/ListActionsOperation.java
@@ -88,6 +88,18 @@
         }
     }
 
+    /**
+     * Execute the list of actions
+     *
+     * @param context the RemoteContext
+     * @param document the current document
+     * @param component the component we belong to
+     * @param x the x touch down coordinate
+     * @param y the y touch down coordinate
+     * @param force if true, will apply the actions even if the component is not visible / not
+     *     containing the touch down coordinates
+     * @return true if we applied the actions, false otherwise
+     */
     public boolean applyActions(
             RemoteContext context,
             CoreDocument document,
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
index f5954ee..0f4cf56 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/LoopOperation.java
@@ -33,6 +33,7 @@
 
 /** Represents a loop of operations */
 public class LoopOperation extends PaintOperation implements Container, VariableSupport {
+
     private static final int OP_CODE = Operations.LOOP_START;
 
     @NonNull public ArrayList<Operation> mList = new ArrayList<>();
@@ -77,6 +78,7 @@
         mIndexVariableId = indexId;
     }
 
+    @Override
     @NonNull
     public ArrayList<Operation> getList() {
         return mList;
@@ -139,6 +141,15 @@
         return "Loop";
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param indexId
+     * @param from
+     * @param step
+     * @param until
+     */
     public static void apply(
             @NonNull WireBuffer buffer, int indexId, float from, float step, float until) {
         buffer.start(OP_CODE);
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
index baff5ee..f94cda2 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/RootLayoutComponent.java
@@ -174,6 +174,11 @@
         context.restore();
     }
 
+    /**
+     * Display the component hierarchy
+     *
+     * @return a formatted string containing the component hierarchy
+     */
     @NonNull
     public String displayHierarchy() {
         StringSerializer serializer = new StringSerializer();
@@ -181,6 +186,13 @@
         return serializer.toString();
     }
 
+    /**
+     * Display the component hierarchy
+     *
+     * @param component the current component
+     * @param indent the current indentation level
+     * @param serializer the serializer we write to
+     */
     public void displayHierarchy(
             @NonNull Component component, int indent, @NonNull StringSerializer serializer) {
         component.serializeToString(indent, serializer);
@@ -214,6 +226,12 @@
         return Operations.LAYOUT_ROOT;
     }
 
+    /**
+     * Write the operation on the buffer
+     *
+     * @param buffer
+     * @param componentId
+     */
     public static void apply(@NonNull WireBuffer buffer, int componentId) {
         buffer.start(Operations.LAYOUT_ROOT);
         buffer.writeInt(componentId);
@@ -249,6 +267,11 @@
         apply(buffer, mComponentId);
     }
 
+    /**
+     * Returns true if we have components with a touch listener
+     *
+     * @return true if listeners, false otherwise
+     */
     public boolean hasTouchListeners() {
         return mHasTouchListeners;
     }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
index 842c9c1..96e29cd 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/layout/utils/DebugLog.java
@@ -40,6 +40,11 @@
             }
         }
 
+        /**
+         * Add a node to the current node
+         *
+         * @param node
+         */
         public void add(@NonNull Node node) {
             list.add(node);
         }
@@ -54,23 +59,35 @@
     @NonNull public static Node node = new Node(null, "Root");
     @NonNull public static Node currentNode = node;
 
+    /** clear the current logging */
     public static void clear() {
         node = new Node(null, "Root");
         currentNode = node;
     }
 
+    /**
+     * start a node
+     *
+     * @param valueSupplier
+     */
     public static void s(@NonNull StringValueSupplier valueSupplier) {
         if (DEBUG_LAYOUT_ON) {
             currentNode = new Node(currentNode, valueSupplier.getString());
         }
     }
 
+    /**
+     * arbitrary log statement
+     *
+     * @param valueSupplier
+     */
     public static void log(@NonNull StringValueSupplier valueSupplier) {
         if (DEBUG_LAYOUT_ON) {
             new LogNode(currentNode, valueSupplier.getString());
         }
     }
 
+    /** end a node */
     public static void e() {
         if (DEBUG_LAYOUT_ON) {
             if (currentNode.parent != null) {
@@ -81,6 +98,11 @@
         }
     }
 
+    /**
+     * end a node
+     *
+     * @param valueSupplier
+     */
     public static void e(@NonNull StringValueSupplier valueSupplier) {
         if (DEBUG_LAYOUT_ON) {
             currentNode.endString = valueSupplier.getString();
@@ -92,6 +114,13 @@
         }
     }
 
+    /**
+     * print a given node
+     *
+     * @param indent
+     * @param node
+     * @param builder
+     */
     public static void printNode(int indent, @NonNull Node node, @NonNull StringBuilder builder) {
         if (DEBUG_LAYOUT_ON) {
             StringBuilder indentationBuilder = new StringBuilder();
@@ -121,6 +150,7 @@
         }
     }
 
+    /** Output the captured log to System.out */
     public static void display() {
         if (DEBUG_LAYOUT_ON) {
             StringBuilder builder = new StringBuilder();
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
index 7e46701..b2ea0af 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/AnimatedFloatExpression.java
@@ -162,7 +162,7 @@
     /** VAR2 operator */
     public static final float VAR3 = asNan(OFFSET + 43);
 
-    // TODO CLAMP, CBRT, DEG, RAD, EXPM1, CEIL, FLOOR
+    // TODO SQUARE, DUP, HYPOT, SWAP
     //    private static final float FP_PI = (float) Math.PI;
     private static final float FP_TO_RAD = 57.29578f; // 180/PI
     private static final float FP_TO_DEG = 0.017453292f; // 180/PI
@@ -172,7 +172,7 @@
     @NonNull float[] mVar = new float[0];
     @Nullable CollectionsAccess mCollectionsAccess;
     IntMap<MonotonicSpline> mSplineMap = new IntMap<>();
-    private Random mRandom;
+    private static Random sRandom;
 
     private float getSplineValue(int arrayId, float pos) {
         MonotonicSpline fit = mSplineMap.get(arrayId);
@@ -806,21 +806,21 @@
                 return sp - 1;
 
             case OP_RAND:
-                if (mRandom == null) {
-                    mRandom = new Random();
+                if (sRandom == null) {
+                    sRandom = new Random();
                 }
-                mStack[sp + 1] = mRandom.nextFloat();
+                mStack[sp + 1] = sRandom.nextFloat();
                 return sp + 1;
 
             case OP_RAND_SEED:
                 float seed = mStack[sp];
                 if (seed == 0) {
-                    mRandom = new Random();
+                    sRandom = new Random();
                 } else {
-                    if (mRandom == null) {
-                        mRandom = new Random(Float.floatToRawIntBits(seed));
+                    if (sRandom == null) {
+                        sRandom = new Random(Float.floatToRawIntBits(seed));
                     } else {
-                        mRandom.setSeed(Float.floatToRawIntBits(seed));
+                        sRandom.setSeed(Float.floatToRawIntBits(seed));
                     }
                 }
                 return sp - 1;
diff --git a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java
index c7e2442..56a0410 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/operations/utilities/touch/VelocityEasing.java
@@ -108,14 +108,14 @@
                 return mStage[i].getPos(t);
             }
         }
-        var ret = (float) getEasing((t - mStage[lastStages].mStartTime));
+        float ret = (float) getEasing((t - mStage[lastStages].mStartTime));
         ret += mStage[lastStages].mStartPos;
         return ret;
     }
 
     @Override
     public String toString() {
-        var s = " ";
+        String s = " ";
         for (int i = 0; i < mNumberOfStages; i++) {
             Stage stage = mStage[i];
             s += " $i $stage";
diff --git a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibilityModifier.java b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibilityModifier.java
index cd8b7b8..098c4c3 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibilityModifier.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibilityModifier.java
@@ -17,7 +17,20 @@
 
 import com.android.internal.widget.remotecompose.core.operations.layout.modifiers.ModifierOperation;
 
-/** A Modifier that provides semantic info. */
+/**
+ * A Modifier that provides semantic info.
+ *
+ * <p>This is needed since `AccessibilityModifier` is generally an open set and designed to be
+ * extended.
+ */
 public interface AccessibilityModifier extends ModifierOperation, AccessibleComponent {
+    /**
+     * This method retrieves the operation code.
+     *
+     * <p>This function is used to get the current operation code associated with the object or
+     * context this method belongs to.
+     *
+     * @return The operation code as an integer.
+     */
     int getOpCode();
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
index e07fc4d..cc6c2a6 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/semantics/AccessibleComponent.java
@@ -17,29 +17,100 @@
 
 import android.annotation.Nullable;
 
+/**
+ * Interface representing an accessible component in the UI. This interface defines properties and
+ * methods related to accessibility semantics for a component. It extends the {@link
+ * AccessibilitySemantics} interface to inherit semantic properties.
+ *
+ * <p>This is similar to {@link CoreSemantics} but handles built in operations that also expose
+ * those core semantics.
+ */
 public interface AccessibleComponent extends AccessibilitySemantics {
+    /**
+     * Returns the ID of the content description for this item.
+     *
+     * <p>The content description is used to provide textual information about the item to
+     * accessibility services, such as screen readers. This allows users with visual impairments to
+     * understand the purpose and content of the item.
+     *
+     * <p>This is similar to AccessibilityNodeInfo.getContentDescription().
+     *
+     * @return The ID of a RemoteString for the content description, or null if no content
+     *     description is provided.
+     */
     default @Nullable Integer getContentDescriptionId() {
         return null;
     }
 
+    /**
+     * Gets the text ID associated with this object.
+     *
+     * <p>This method is intended to be overridden by subclasses that need to associate a specific
+     * text ID with themselves. The default implementation returns null, indicating that no text ID
+     * is associated with the object.
+     *
+     * <p>This is similar to AccessibilityNodeInfo.getText().
+     *
+     * @return The text ID, or null if no text ID is associated with this object.
+     */
     default @Nullable Integer getTextId() {
         return null;
     }
 
+    /**
+     * Retrieves the role associated with this object. The enum type deliberately matches the
+     * Compose Role. In the platform it will be applied as ROLE_DESCRIPTION_KEY.
+     *
+     * <p>The default implementation returns {@code null}, indicating that no role is assigned.
+     *
+     * @return The role associated with this object, or {@code null} if no role is assigned.
+     */
     default @Nullable Role getRole() {
         return null;
     }
 
+    /**
+     * Checks if the element is clickable.
+     *
+     * <p>By default, elements are not considered clickable. Subclasses should override this method
+     * to indicate clickability based on their specific properties and behavior.
+     *
+     * <p>This is similar to AccessibilityNodeInfo.isClickable().
+     *
+     * @return {@code true} if the element is clickable, {@code false} otherwise.
+     */
     default boolean isClickable() {
         return false;
     }
 
+    /**
+     * Gets the merge mode of the operation.
+     *
+     * <p>The mode indicates the type of operation being performed. By default it returns {@link
+     * CoreSemantics.Mode#SET}, indicating a "set" operation.
+     *
+     * <p>{@link CoreSemantics.Mode#CLEAR_AND_SET} matches a Compose modifier of
+     * `Modifier.clearAndSetSemantics {}`
+     *
+     * <p>{@link CoreSemantics.Mode#MERGE} matches a Compose modifier of
+     * `Modifier.semantics(mergeDescendants = true) {}`
+     *
+     * @return The mode of the operation, which defaults to {@link CoreSemantics.Mode#SET}.
+     */
     default CoreSemantics.Mode getMode() {
         return CoreSemantics.Mode.SET;
     }
 
-    // Our master list
-    // https://developer.android.com/reference/kotlin/androidx/compose/ui/semantics/Role
+    /**
+     * Represents the role of an accessible component.
+     *
+     * <p>The enum type deliberately matches the Compose Role. In the platform it will be applied as
+     * ROLE_DESCRIPTION_KEY.
+     *
+     * @link <a
+     *     href="https://developer.android.com/reference/androidx/compose/ui/semantics/Role">Compose
+     *     Semantics Role</a>
+     */
     enum Role {
         BUTTON("Button"),
         CHECKBOX("Checkbox"),
@@ -70,4 +141,21 @@
             return Role.UNKNOWN;
         }
     }
+
+    /**
+     * Defines the merge mode of an element in the semantic tree.
+     *
+     * <p>{@link CoreSemantics.Mode#CLEAR_AND_SET} matches a Compose modifier of
+     * `Modifier.clearAndSetSemantics {}`
+     *
+     * <p>{@link CoreSemantics.Mode#MERGE} matches a Compose modifier of
+     * `Modifier.semantics(mergeDescendants = true) {}`
+     *
+     * <p>{@link CoreSemantics.Mode#SET} adds or overrides semantics on an element.
+     */
+    enum Mode {
+        SET,
+        CLEAR_AND_SET,
+        MERGE
+    }
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java b/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java
index 4047dd2..5b35ee5 100644
--- a/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java
+++ b/core/java/com/android/internal/widget/remotecompose/core/semantics/CoreSemantics.java
@@ -118,16 +118,22 @@
         return indent + this;
     }
 
-    @NonNull
-    public String serializedName() {
-        return "SEMANTICS";
-    }
-
     @Override
     public void serializeToString(int indent, @NonNull StringSerializer serializer) {
-        serializer.append(indent, serializedName() + " = " + this);
+        serializer.append(indent, "SEMANTICS" + " = " + this);
     }
 
+    /**
+     * Reads a CoreSemantics object from a WireBuffer and adds it to a list of operations.
+     *
+     * <p>This method reads the data required to construct a CoreSemantics object from the provided
+     * WireBuffer. After reading and constructing the CoreSemantics object, it is added to the
+     * provided list of operations.
+     *
+     * @param buffer The WireBuffer to read data from.
+     * @param operations The list of operations to which the read CoreSemantics object will be
+     *     added.
+     */
     public static void read(WireBuffer buffer, List<Operation> operations) {
         CoreSemantics semantics = new CoreSemantics();
 
@@ -148,10 +154,4 @@
     public @Nullable Integer getTextId() {
         return mTextId != 0 ? mTextId : null;
     }
-
-    public enum Mode {
-        SET,
-        CLEAR_AND_SET,
-        MERGE
-    }
 }
diff --git a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
index da65a9c..970cc4a 100644
--- a/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
+++ b/core/java/com/android/internal/widget/remotecompose/player/platform/RemoteComposeCanvas.java
@@ -19,7 +19,9 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Paint;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.Choreographer;
 import android.view.MotionEvent;
@@ -47,6 +49,7 @@
     Point mActionDownPoint = new Point(0, 0);
     AndroidRemoteContext mARContext = new AndroidRemoteContext();
     float mDensity = 1f;
+    long mStart = System.nanoTime();
 
     long mLastFrameDelay = 1;
     float mMaxFrameRate = 60f; // frames per seconds
@@ -103,12 +106,14 @@
     public void setDocument(RemoteComposeDocument value) {
         mDocument = value;
         mDocument.initializeContext(mARContext);
+        mDisable = false;
         mARContext.setAnimationEnabled(true);
         mARContext.setDensity(mDensity);
         mARContext.setUseChoreographer(true);
         setContentDescription(mDocument.getDocument().getContentDescription());
         updateClickAreas();
         requestLayout();
+        mARContext.loadFloat(RemoteContext.ID_TOUCH_EVENT_TIME, -Float.MAX_VALUE);
         invalidate();
     }
 
@@ -337,6 +342,8 @@
                 mActionDownPoint.y = (int) event.getY();
                 CoreDocument doc = mDocument.getDocument();
                 if (doc.hasTouchListener()) {
+                    mARContext.loadFloat(
+                            RemoteContext.ID_TOUCH_EVENT_TIME, mARContext.getAnimationTime());
                     mInActionDown = true;
                     if (mVelocityTracker == null) {
                         mVelocityTracker = VelocityTracker.obtain();
@@ -368,6 +375,8 @@
                 performClick();
                 doc = mDocument.getDocument();
                 if (doc.hasTouchListener()) {
+                    mARContext.loadFloat(
+                            RemoteContext.ID_TOUCH_EVENT_TIME, mARContext.getAnimationTime());
                     mVelocityTracker.computeCurrentVelocity(1000);
                     float dx = mVelocityTracker.getXVelocity(pointerId);
                     float dy = mVelocityTracker.getYVelocity(pointerId);
@@ -380,6 +389,8 @@
             case MotionEvent.ACTION_MOVE:
                 if (mInActionDown) {
                     if (mVelocityTracker != null) {
+                        mARContext.loadFloat(
+                                RemoteContext.ID_TOUCH_EVENT_TIME, mARContext.getAnimationTime());
                         mVelocityTracker.addMovement(event);
                         doc = mDocument.getDocument();
                         boolean repaint = doc.touchDrag(mARContext, event.getX(), event.getY());
@@ -453,7 +464,9 @@
     private int mCount;
     private long mTime = System.nanoTime();
     private long mDuration;
-    private boolean mEvalTime = false;
+    private boolean mEvalTime = false; // turn on to measure eval time
+    private float mLastAnimationTime = 0.1f; // set to random non 0 number
+    private boolean mDisable = false;
 
     /**
      * This returns the amount of time in ms the player used to evalueate a pass it is averaged over
@@ -480,36 +493,76 @@
         if (mDocument == null) {
             return;
         }
-        long start = mEvalTime ? System.nanoTime() : 0;
-        mARContext.useCanvas(canvas);
-        mARContext.mWidth = getWidth();
-        mARContext.mHeight = getHeight();
-        mDocument.paint(mARContext, mTheme);
-        if (mDebug == 1) {
-            mCount++;
-            if (System.nanoTime() - mTime > 1000000000L) {
-                System.out.println(" count " + mCount + " fps");
-                mCount = 0;
-                mTime = System.nanoTime();
-            }
+        if (mDisable) {
+            drawDisable(canvas);
+            return;
         }
-        int nextFrame = mDocument.needsRepaint();
-        if (nextFrame > 0) {
-            mLastFrameDelay = Math.max(mMaxFrameDelay, nextFrame);
-            if (mChoreographer != null) {
-                mChoreographer.postFrameCallbackDelayed(mFrameCallback, mLastFrameDelay);
+        try {
+
+            long start = mEvalTime ? System.nanoTime() : 0; // measure execut of commands
+
+            float animationTime = (System.nanoTime() - mStart) * 1E-9f;
+            mARContext.setAnimationTime(animationTime);
+            mARContext.loadFloat(RemoteContext.ID_ANIMATION_TIME, animationTime);
+            float loopTime = animationTime - mLastAnimationTime;
+            mARContext.loadFloat(RemoteContext.ID_ANIMATION_DELTA_TIME, loopTime);
+            mLastAnimationTime = animationTime;
+            mARContext.setAnimationEnabled(true);
+            mARContext.currentTime = System.currentTimeMillis();
+            mARContext.setDebug(mDebug);
+            float density = getContext().getResources().getDisplayMetrics().density;
+            mARContext.useCanvas(canvas);
+            mARContext.mWidth = getWidth();
+            mARContext.mHeight = getHeight();
+            mDocument.paint(mARContext, mTheme);
+            if (mDebug == 1) {
+                mCount++;
+                if (System.nanoTime() - mTime > 1000000000L) {
+                    System.out.println(" count " + mCount + " fps");
+                    mCount = 0;
+                    mTime = System.nanoTime();
+                }
             }
-            if (!mARContext.useChoreographer()) {
-                invalidate();
+            int nextFrame = mDocument.needsRepaint();
+            if (nextFrame > 0) {
+                mLastFrameDelay = Math.max(mMaxFrameDelay, nextFrame);
+                if (mChoreographer != null) {
+                    mChoreographer.postFrameCallbackDelayed(mFrameCallback, mLastFrameDelay);
+                }
+                if (!mARContext.useChoreographer()) {
+                    invalidate();
+                }
+            } else {
+                if (mChoreographer != null) {
+                    mChoreographer.removeFrameCallback(mFrameCallback);
+                }
             }
-        } else {
-            if (mChoreographer != null) {
-                mChoreographer.removeFrameCallback(mFrameCallback);
+            if (mEvalTime) {
+                mDuration += System.nanoTime() - start;
+                mCount++;
             }
+        } catch (Exception ex) {
+            mARContext.getLastOpCount();
+            mDisable = true;
+            invalidate();
         }
-        if (mEvalTime) {
-            mDuration += System.nanoTime() - start;
-            mCount++;
-        }
+    }
+
+    private void drawDisable(Canvas canvas) {
+        Rect rect = new Rect();
+        canvas.drawColor(Color.BLACK);
+        Paint paint = new Paint();
+        paint.setTextSize(128f);
+        paint.setColor(Color.RED);
+        int w = getWidth();
+        int h = getHeight();
+
+        String str = "⚠";
+        paint.getTextBounds(str, 0, 1, rect);
+
+        float x = w / 2f - rect.width() / 2f - rect.left;
+        float y = h / 2f + rect.height() / 2f - rect.bottom;
+
+        canvas.drawText(str, x, y, paint);
     }
 }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 027113a..3afe27e 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -179,6 +179,8 @@
                 "android_os_NativeHandle.cpp",
                 "android_os_MemoryFile.cpp",
                 "android_os_MessageQueue.cpp",
+                "android_os_PerfettoTrace.cpp",
+                "android_os_PerfettoTrackEventExtra.cpp",
                 "android_os_Parcel.cpp",
                 "android_os_PerformanceHintManager.cpp",
                 "android_os_SELinux.cpp",
@@ -482,11 +484,22 @@
                 "libbinder",
                 "libhidlbase", // libhwbinder is in here
             ],
+            version_script: "platform/linux/libandroid_runtime_export.txt",
+        },
+        darwin: {
+            host_ldlibs: [
+                "-framework AppKit",
+            ],
+            dist: {
+                targets: ["layoutlib_jni"],
+                dir: "layoutlib_native/darwin",
+            },
+            exported_symbols_list: "platform/darwin/libandroid_runtime_export.exp",
         },
         linux_glibc_x86_64: {
             ldflags: ["-static-libgcc"],
             dist: {
-                targets: ["layoutlib"],
+                targets: ["layoutlib_jni"],
                 dir: "layoutlib_native/linux",
                 tag: "stripped_all",
             },
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 78d69f0..aea1734 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -158,6 +158,8 @@
 extern int register_android_os_storage_StorageManager(JNIEnv* env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
+extern int register_android_os_PerfettoTrace(JNIEnv* env);
+extern int register_android_os_PerfettoTrackEventExtra(JNIEnv* env);
 extern int register_android_os_Trace(JNIEnv* env);
 extern int register_android_os_FileObserver(JNIEnv *env);
 extern int register_android_os_UEventObserver(JNIEnv* env);
@@ -1605,6 +1607,8 @@
         REG_JNI(register_android_os_GraphicsEnvironment),
         REG_JNI(register_android_os_MessageQueue),
         REG_JNI(register_android_os_SELinux),
+        REG_JNI(register_android_os_PerfettoTrace),
+        REG_JNI(register_android_os_PerfettoTrackEventExtra),
         REG_JNI(register_android_os_Trace),
         REG_JNI(register_android_os_UEventObserver),
         REG_JNI(register_android_net_LocalSocketImpl),
diff --git a/core/jni/android_hardware_camera2_CameraDevice.cpp b/core/jni/android_hardware_camera2_CameraDevice.cpp
index 493c707..04cfed5 100644
--- a/core/jni/android_hardware_camera2_CameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_CameraDevice.cpp
@@ -30,6 +30,7 @@
 #include <nativehelper/JNIHelp.h>
 #include "android_os_Parcel.h"
 #include "core_jni_helpers.h"
+#include <android/binder_auto_utils.h>
 #include <android/binder_parcel_jni.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
 #include <aidl/android/hardware/common/fmq/MQDescriptor.h>
@@ -40,6 +41,7 @@
 using namespace android;
 
 using ::android::AidlMessageQueue;
+using ndk::ScopedAParcel;
 using ResultMetadataQueue = AidlMessageQueue<int8_t, SynchronizedReadWrite>;
 
 class FMQReader {
@@ -75,15 +77,16 @@
 
 static jlong CameraDevice_createFMQReader(JNIEnv *env, jclass thiz,
         jobject resultParcel) {
-    AParcel *resultAParcel = AParcel_fromJavaParcel(env, resultParcel);
-    if (resultAParcel == nullptr) {
+    ScopedAParcel sResultAParcel(AParcel_fromJavaParcel(env, resultParcel));
+    if (sResultAParcel.get() == nullptr) {
         ALOGE("%s: Error creating result parcel", __FUNCTION__);
         return 0;
     }
-    AParcel_setDataPosition(resultAParcel, 0);
+
+    AParcel_setDataPosition(sResultAParcel.get(), 0);
 
     MQDescriptor<int8_t, SynchronizedReadWrite> resultMQ;
-    if (resultMQ.readFromParcel(resultAParcel) != OK) {
+    if (resultMQ.readFromParcel(sResultAParcel.get()) != OK) {
         ALOGE("%s: read from result parcel failed", __FUNCTION__);
         return 0;
     }
diff --git a/core/jni/android_os_PerfettoTrace.cpp b/core/jni/android_os_PerfettoTrace.cpp
new file mode 100644
index 0000000..988aea7
--- /dev/null
+++ b/core/jni/android_os_PerfettoTrace.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <cutils/compiler.h>
+#include <cutils/trace.h>
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/scoped_local_ref.h>
+#include <nativehelper/scoped_primitive_array.h>
+#include <nativehelper/scoped_utf_chars.h>
+#include <tracing_sdk.h>
+
+namespace android {
+template <typename T>
+inline static T* toPointer(jlong ptr) {
+    return reinterpret_cast<T*>(static_cast<uintptr_t>(ptr));
+}
+
+template <typename T>
+inline static jlong toJLong(T* ptr) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
+}
+
+static const char* fromJavaString(JNIEnv* env, jstring jstr) {
+    if (!jstr) return "";
+    ScopedUtfChars chars(env, jstr);
+
+    if (!chars.c_str()) {
+        ALOGE("Failed extracting string");
+        return "";
+    }
+
+    return chars.c_str();
+}
+
+static void android_os_PerfettoTrace_event(JNIEnv* env, jclass, jint type, jlong cat_ptr,
+                                           jstring name, jlong extra_ptr) {
+    ScopedUtfChars name_utf(env, name);
+    if (!name_utf.c_str()) {
+        ALOGE("Failed extracting string");
+    }
+
+    tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(cat_ptr);
+    tracing_perfetto::trace_event(type, category->get(), name_utf.c_str(),
+                                  toPointer<tracing_perfetto::Extra>(extra_ptr));
+}
+
+static jlong android_os_PerfettoTrace_get_process_track_uuid() {
+    return tracing_perfetto::get_process_track_uuid();
+}
+
+static jlong android_os_PerfettoTrace_get_thread_track_uuid(jlong tid) {
+    return tracing_perfetto::get_thread_track_uuid(tid);
+}
+
+static void android_os_PerfettoTrace_activate_trigger(JNIEnv* env, jclass, jstring name,
+                                                      jint ttl_ms) {
+    ScopedUtfChars name_utf(env, name);
+    if (!name_utf.c_str()) {
+        ALOGE("Failed extracting string");
+        return;
+    }
+
+    tracing_perfetto::activate_trigger(name_utf.c_str(), static_cast<uint32_t>(ttl_ms));
+}
+
+static jlong android_os_PerfettoTraceCategory_init(JNIEnv* env, jclass, jstring name, jstring tag,
+                                                   jstring severity) {
+    return toJLong(new tracing_perfetto::Category(fromJavaString(env, name),
+                                                  fromJavaString(env, tag),
+                                                  fromJavaString(env, severity)));
+}
+
+static jlong android_os_PerfettoTraceCategory_delete() {
+    return toJLong(&tracing_perfetto::Category::delete_category);
+}
+
+static void android_os_PerfettoTraceCategory_register(jlong ptr) {
+    tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(ptr);
+    category->register_category();
+}
+
+static void android_os_PerfettoTraceCategory_unregister(jlong ptr) {
+    tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(ptr);
+    category->unregister_category();
+}
+
+static jboolean android_os_PerfettoTraceCategory_is_enabled(jlong ptr) {
+    tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(ptr);
+    return category->is_category_enabled();
+}
+
+static jlong android_os_PerfettoTraceCategory_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::Category* category = toPointer<tracing_perfetto::Category>(ptr);
+    return toJLong(category->get());
+}
+
+static const JNINativeMethod gCategoryMethods[] = {
+        {"native_init", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
+         (void*)android_os_PerfettoTraceCategory_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTraceCategory_delete},
+        {"native_register", "(J)V", (void*)android_os_PerfettoTraceCategory_register},
+        {"native_unregister", "(J)V", (void*)android_os_PerfettoTraceCategory_unregister},
+        {"native_is_enabled", "(J)Z", (void*)android_os_PerfettoTraceCategory_is_enabled},
+        {"native_get_extra_ptr", "(J)J", (void*)android_os_PerfettoTraceCategory_get_extra_ptr},
+};
+
+static const JNINativeMethod gTraceMethods[] =
+        {{"native_event", "(IJLjava/lang/String;J)V", (void*)android_os_PerfettoTrace_event},
+         {"native_get_process_track_uuid", "()J",
+          (void*)android_os_PerfettoTrace_get_process_track_uuid},
+         {"native_get_thread_track_uuid", "(J)J",
+          (void*)android_os_PerfettoTrace_get_thread_track_uuid},
+         {"native_activate_trigger", "(Ljava/lang/String;I)V",
+          (void*)android_os_PerfettoTrace_activate_trigger}};
+
+int register_android_os_PerfettoTrace(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/os/PerfettoTrace", gTraceMethods,
+                                       NELEM(gTraceMethods));
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrace$Category", gCategoryMethods,
+                                   NELEM(gCategoryMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/android_os_PerfettoTrackEventExtra.cpp b/core/jni/android_os_PerfettoTrackEventExtra.cpp
new file mode 100644
index 0000000..9adad7b
--- /dev/null
+++ b/core/jni/android_os_PerfettoTrackEventExtra.cpp
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/compiler.h>
+#include <cutils/trace.h>
+#include <jni.h>
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/scoped_utf_chars.h>
+#include <tracing_sdk.h>
+
+static constexpr ssize_t kMaxStrLen = 4096;
+namespace android {
+template <typename T>
+inline static T* toPointer(jlong ptr) {
+    return reinterpret_cast<T*>(static_cast<uintptr_t>(ptr));
+}
+
+template <typename T>
+inline static jlong toJLong(T* ptr) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
+}
+
+static const char* fromJavaString(JNIEnv* env, jstring jstr) {
+    if (!jstr) return "";
+    ScopedUtfChars chars(env, jstr);
+
+    if (!chars.c_str()) {
+        ALOGE("Failed extracting string");
+        return "";
+    }
+
+    return chars.c_str();
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgInt64_init(JNIEnv* env, jclass, jstring name) {
+    return toJLong(new tracing_perfetto::DebugArg<int64_t>(fromJavaString(env, name)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgBool_init(JNIEnv* env, jclass, jstring name) {
+    return toJLong(new tracing_perfetto::DebugArg<bool>(fromJavaString(env, name)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgDouble_init(JNIEnv* env, jclass, jstring name) {
+    return toJLong(new tracing_perfetto::DebugArg<double>(fromJavaString(env, name)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgString_init(JNIEnv* env, jclass, jstring name) {
+    return toJLong(new tracing_perfetto::DebugArg<const char*>(fromJavaString(env, name)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgInt64_delete() {
+    return toJLong(&tracing_perfetto::DebugArg<int64_t>::delete_arg);
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgBool_delete() {
+    return toJLong(&tracing_perfetto::DebugArg<bool>::delete_arg);
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgDouble_delete() {
+    return toJLong(&tracing_perfetto::DebugArg<double>::delete_arg);
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgString_delete() {
+    return toJLong(&tracing_perfetto::DebugArg<const char*>::delete_arg);
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgInt64_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::DebugArg<int64_t>* arg = toPointer<tracing_perfetto::DebugArg<int64_t>>(ptr);
+    return toJLong(arg->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgBool_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::DebugArg<bool>* arg = toPointer<tracing_perfetto::DebugArg<bool>>(ptr);
+    return toJLong(arg->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgDouble_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::DebugArg<double>* arg = toPointer<tracing_perfetto::DebugArg<double>>(ptr);
+    return toJLong(arg->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraArgString_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::DebugArg<const char*>* arg =
+            toPointer<tracing_perfetto::DebugArg<const char*>>(ptr);
+    return toJLong(arg->get());
+}
+
+static void android_os_PerfettoTrackEventExtraArgInt64_set_value(jlong ptr, jlong val) {
+    tracing_perfetto::DebugArg<int64_t>* arg = toPointer<tracing_perfetto::DebugArg<int64_t>>(ptr);
+    arg->set_value(val);
+}
+
+static void android_os_PerfettoTrackEventExtraArgBool_set_value(jlong ptr, jboolean val) {
+    tracing_perfetto::DebugArg<bool>* arg = toPointer<tracing_perfetto::DebugArg<bool>>(ptr);
+    arg->set_value(val);
+}
+
+static void android_os_PerfettoTrackEventExtraArgDouble_set_value(jlong ptr, jdouble val) {
+    tracing_perfetto::DebugArg<double>* arg = toPointer<tracing_perfetto::DebugArg<double>>(ptr);
+    arg->set_value(val);
+}
+
+static void android_os_PerfettoTrackEventExtraArgString_set_value(JNIEnv* env, jclass, jlong ptr,
+                                                                  jstring val) {
+    tracing_perfetto::DebugArg<const char*>* arg =
+            toPointer<tracing_perfetto::DebugArg<const char*>>(ptr);
+    arg->set_value(strdup(fromJavaString(env, val)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldInt64_init() {
+    return toJLong(new tracing_perfetto::ProtoField<int64_t>());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldDouble_init() {
+    return toJLong(new tracing_perfetto::ProtoField<double>());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldString_init() {
+    return toJLong(new tracing_perfetto::ProtoField<const char*>());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldNested_init() {
+    return toJLong(new tracing_perfetto::ProtoFieldNested());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldInt64_delete() {
+    return toJLong(&tracing_perfetto::ProtoField<int64_t>::delete_field);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldDouble_delete() {
+    return toJLong(&tracing_perfetto::ProtoField<double>::delete_field);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldString_delete() {
+    return toJLong(&tracing_perfetto::ProtoField<const char*>::delete_field);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldNested_delete() {
+    return toJLong(&tracing_perfetto::ProtoFieldNested::delete_field);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldInt64_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::ProtoField<int64_t>* field =
+            toPointer<tracing_perfetto::ProtoField<int64_t>>(ptr);
+    return toJLong(field->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldDouble_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::ProtoField<double>* field =
+            toPointer<tracing_perfetto::ProtoField<double>>(ptr);
+    return toJLong(field->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldString_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::ProtoField<const char*>* field =
+            toPointer<tracing_perfetto::ProtoField<const char*>>(ptr);
+    return toJLong(field->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraFieldNested_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::ProtoFieldNested* field = toPointer<tracing_perfetto::ProtoFieldNested>(ptr);
+    return toJLong(field->get());
+}
+
+static void android_os_PerfettoTrackEventExtraFieldInt64_set_value(jlong ptr, jlong id, jlong val) {
+    tracing_perfetto::ProtoField<int64_t>* field =
+            toPointer<tracing_perfetto::ProtoField<int64_t>>(ptr);
+    field->set_value(id, val);
+}
+
+static void android_os_PerfettoTrackEventExtraFieldDouble_set_value(jlong ptr, jlong id,
+                                                                    jdouble val) {
+    tracing_perfetto::ProtoField<double>* field =
+            toPointer<tracing_perfetto::ProtoField<double>>(ptr);
+    field->set_value(id, val);
+}
+
+static void android_os_PerfettoTrackEventExtraFieldString_set_value(JNIEnv* env, jclass, jlong ptr,
+                                                                    jlong id, jstring val) {
+    tracing_perfetto::ProtoField<const char*>* field =
+            toPointer<tracing_perfetto::ProtoField<const char*>>(ptr);
+    field->set_value(id, strdup(fromJavaString(env, val)));
+}
+
+static void android_os_PerfettoTrackEventExtraFieldNested_add_field(jlong field_ptr,
+                                                                    jlong arg_ptr) {
+    tracing_perfetto::ProtoFieldNested* field =
+            toPointer<tracing_perfetto::ProtoFieldNested>(field_ptr);
+    field->add_field(toPointer<PerfettoTeHlProtoField>(arg_ptr));
+}
+
+static void android_os_PerfettoTrackEventExtraFieldNested_set_id(jlong ptr, jlong id) {
+    tracing_perfetto::ProtoFieldNested* field = toPointer<tracing_perfetto::ProtoFieldNested>(ptr);
+    field->set_id(id);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFlow_init() {
+    return toJLong(new tracing_perfetto::Flow());
+}
+
+static void android_os_PerfettoTrackEventExtraFlow_set_process_flow(jlong ptr, jlong id) {
+    tracing_perfetto::Flow* flow = toPointer<tracing_perfetto::Flow>(ptr);
+    flow->set_process_flow(id);
+}
+
+static void android_os_PerfettoTrackEventExtraFlow_set_process_terminating_flow(jlong ptr,
+                                                                                jlong id) {
+    tracing_perfetto::Flow* flow = toPointer<tracing_perfetto::Flow>(ptr);
+    flow->set_process_terminating_flow(id);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFlow_delete() {
+    return toJLong(&tracing_perfetto::Flow::delete_flow);
+}
+
+static jlong android_os_PerfettoTrackEventExtraFlow_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::Flow* flow = toPointer<tracing_perfetto::Flow>(ptr);
+    return toJLong(flow->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraNamedTrack_init(JNIEnv* env, jclass, jlong id,
+                                                               jstring name, jlong parent_uuid) {
+    return toJLong(new tracing_perfetto::NamedTrack(id, parent_uuid, fromJavaString(env, name)));
+}
+
+static jlong android_os_PerfettoTrackEventExtraNamedTrack_delete() {
+    return toJLong(&tracing_perfetto::NamedTrack::delete_track);
+}
+
+static jlong android_os_PerfettoTrackEventExtraNamedTrack_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::NamedTrack* track = toPointer<tracing_perfetto::NamedTrack>(ptr);
+    return toJLong(track->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterTrack_init(JNIEnv* env, jclass, jstring name,
+                                                                 jlong parent_uuid) {
+    return toJLong(
+            new tracing_perfetto::RegisteredTrack(1, parent_uuid, fromJavaString(env, name), true));
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterTrack_delete() {
+    return toJLong(&tracing_perfetto::RegisteredTrack::delete_track);
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterTrack_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::RegisteredTrack* track = toPointer<tracing_perfetto::RegisteredTrack>(ptr);
+    return toJLong(track->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterInt64_init() {
+    return toJLong(new tracing_perfetto::Counter<int64_t>());
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterInt64_delete() {
+    return toJLong(&tracing_perfetto::Counter<int64_t>::delete_counter);
+}
+
+static void android_os_PerfettoTrackEventExtraCounterInt64_set_value(jlong ptr, jlong val) {
+    tracing_perfetto::Counter<int64_t>* counter =
+            toPointer<tracing_perfetto::Counter<int64_t>>(ptr);
+    counter->set_value(val);
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterInt64_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::Counter<int64_t>* counter =
+            toPointer<tracing_perfetto::Counter<int64_t>>(ptr);
+    return toJLong(counter->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterDouble_init() {
+    return toJLong(new tracing_perfetto::Counter<double>());
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterDouble_delete() {
+    return toJLong(&tracing_perfetto::Counter<double>::delete_counter);
+}
+
+static void android_os_PerfettoTrackEventExtraCounterDouble_set_value(jlong ptr, jdouble val) {
+    tracing_perfetto::Counter<double>* counter = toPointer<tracing_perfetto::Counter<double>>(ptr);
+    counter->set_value(val);
+}
+
+static jlong android_os_PerfettoTrackEventExtraCounterDouble_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::Counter<double>* counter = toPointer<tracing_perfetto::Counter<double>>(ptr);
+    return toJLong(counter->get());
+}
+
+static jlong android_os_PerfettoTrackEventExtra_init() {
+    return toJLong(new tracing_perfetto::Extra());
+}
+
+static jlong android_os_PerfettoTrackEventExtra_delete() {
+    return toJLong(&tracing_perfetto::Extra::delete_extra);
+}
+
+static void android_os_PerfettoTrackEventExtra_add_arg(jlong extra_ptr, jlong arg_ptr) {
+    tracing_perfetto::Extra* extra = toPointer<tracing_perfetto::Extra>(extra_ptr);
+    extra->push_extra(toPointer<PerfettoTeHlExtra>(arg_ptr));
+}
+
+static void android_os_PerfettoTrackEventExtra_clear_args(jlong ptr) {
+    tracing_perfetto::Extra* extra = toPointer<tracing_perfetto::Extra>(ptr);
+    extra->clear_extras();
+}
+
+static jlong android_os_PerfettoTrackEventExtraProto_init() {
+    return toJLong(new tracing_perfetto::Proto());
+}
+
+static jlong android_os_PerfettoTrackEventExtraProto_delete() {
+    return toJLong(&tracing_perfetto::Proto::delete_proto);
+}
+
+static jlong android_os_PerfettoTrackEventExtraProto_get_extra_ptr(jlong ptr) {
+    tracing_perfetto::Proto* proto = toPointer<tracing_perfetto::Proto>(ptr);
+    return toJLong(proto->get());
+}
+
+static void android_os_PerfettoTrackEventExtraProto_add_field(long proto_ptr, jlong arg_ptr) {
+    tracing_perfetto::Proto* proto = toPointer<tracing_perfetto::Proto>(proto_ptr);
+    proto->add_field(toPointer<PerfettoTeHlProtoField>(arg_ptr));
+}
+
+static void android_os_PerfettoTrackEventExtraProto_clear_fields(jlong ptr) {
+    tracing_perfetto::Proto* proto = toPointer<tracing_perfetto::Proto>(ptr);
+    proto->clear_fields();
+}
+
+static const JNINativeMethod gExtraMethods[] =
+        {{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtra_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtra_delete},
+         {"native_add_arg", "(JJ)V", (void*)android_os_PerfettoTrackEventExtra_add_arg},
+         {"native_clear_args", "(J)V", (void*)android_os_PerfettoTrackEventExtra_clear_args}};
+
+static const JNINativeMethod gProtoMethods[] =
+        {{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraProto_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraProto_delete},
+         {"native_get_extra_ptr", "(J)J",
+          (void*)android_os_PerfettoTrackEventExtraProto_get_extra_ptr},
+         {"native_add_field", "(JJ)V", (void*)android_os_PerfettoTrackEventExtraProto_add_field},
+         {"native_clear_fields", "(J)V",
+          (void*)android_os_PerfettoTrackEventExtraProto_clear_fields}};
+
+static const JNINativeMethod gArgInt64Methods[] = {
+        {"native_init", "(Ljava/lang/String;)J",
+         (void*)android_os_PerfettoTrackEventExtraArgInt64_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraArgInt64_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraArgInt64_get_extra_ptr},
+        {"native_set_value", "(JJ)V", (void*)android_os_PerfettoTrackEventExtraArgInt64_set_value},
+};
+
+static const JNINativeMethod gArgBoolMethods[] = {
+        {"native_init", "(Ljava/lang/String;)J",
+         (void*)android_os_PerfettoTrackEventExtraArgBool_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraArgBool_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraArgBool_get_extra_ptr},
+        {"native_set_value", "(JZ)V", (void*)android_os_PerfettoTrackEventExtraArgBool_set_value},
+};
+
+static const JNINativeMethod gArgDoubleMethods[] = {
+        {"native_init", "(Ljava/lang/String;)J",
+         (void*)android_os_PerfettoTrackEventExtraArgDouble_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraArgDouble_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraArgDouble_get_extra_ptr},
+        {"native_set_value", "(JD)V", (void*)android_os_PerfettoTrackEventExtraArgDouble_set_value},
+};
+
+static const JNINativeMethod gArgStringMethods[] = {
+        {"native_init", "(Ljava/lang/String;)J",
+         (void*)android_os_PerfettoTrackEventExtraArgString_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraArgString_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraArgString_get_extra_ptr},
+        {"native_set_value", "(JLjava/lang/String;)V",
+         (void*)android_os_PerfettoTrackEventExtraArgString_set_value},
+};
+
+static const JNINativeMethod gFieldInt64Methods[] = {
+        {"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraFieldInt64_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraFieldInt64_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraFieldInt64_get_extra_ptr},
+        {"native_set_value", "(JJJ)V",
+         (void*)android_os_PerfettoTrackEventExtraFieldInt64_set_value},
+};
+
+static const JNINativeMethod gFieldDoubleMethods[] = {
+        {"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraFieldDouble_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraFieldDouble_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraFieldDouble_get_extra_ptr},
+        {"native_set_value", "(JJD)V",
+         (void*)android_os_PerfettoTrackEventExtraFieldDouble_set_value},
+};
+
+static const JNINativeMethod gFieldStringMethods[] = {
+        {"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraFieldString_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraFieldString_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraFieldString_get_extra_ptr},
+        {"native_set_value", "(JJLjava/lang/String;)V",
+         (void*)android_os_PerfettoTrackEventExtraFieldString_set_value},
+};
+
+static const JNINativeMethod gFieldNestedMethods[] =
+        {{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraFieldNested_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraFieldNested_delete},
+         {"native_get_extra_ptr", "(J)J",
+          (void*)android_os_PerfettoTrackEventExtraFieldNested_get_extra_ptr},
+         {"native_add_field", "(JJ)V",
+          (void*)android_os_PerfettoTrackEventExtraFieldNested_add_field},
+         {"native_set_id", "(JJ)V", (void*)android_os_PerfettoTrackEventExtraFieldNested_set_id}};
+
+static const JNINativeMethod gFlowMethods[] = {
+        {"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraFlow_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraFlow_delete},
+        {"native_set_process_flow", "(JJ)V",
+         (void*)android_os_PerfettoTrackEventExtraFlow_set_process_flow},
+        {"native_set_process_terminating_flow", "(JJ)V",
+         (void*)android_os_PerfettoTrackEventExtraFlow_set_process_terminating_flow},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraFlow_get_extra_ptr},
+};
+
+static const JNINativeMethod gNamedTrackMethods[] = {
+        {"native_init", "(JLjava/lang/String;J)J",
+         (void*)android_os_PerfettoTrackEventExtraNamedTrack_init},
+        {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraNamedTrack_delete},
+        {"native_get_extra_ptr", "(J)J",
+         (void*)android_os_PerfettoTrackEventExtraNamedTrack_get_extra_ptr},
+};
+
+static const JNINativeMethod gCounterTrackMethods[] =
+        {{"native_init", "(Ljava/lang/String;J)J",
+          (void*)android_os_PerfettoTrackEventExtraCounterTrack_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraCounterTrack_delete},
+         {"native_get_extra_ptr", "(J)J",
+          (void*)android_os_PerfettoTrackEventExtraCounterTrack_get_extra_ptr}};
+
+static const JNINativeMethod gCounterInt64Methods[] =
+        {{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraCounterInt64_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraCounterInt64_delete},
+         {"native_set_value", "(JJ)V",
+          (void*)android_os_PerfettoTrackEventExtraCounterInt64_set_value},
+         {"native_get_extra_ptr", "(J)J",
+          (void*)android_os_PerfettoTrackEventExtraCounterInt64_get_extra_ptr}};
+
+static const JNINativeMethod gCounterDoubleMethods[] =
+        {{"native_init", "()J", (void*)android_os_PerfettoTrackEventExtraCounterDouble_init},
+         {"native_delete", "()J", (void*)android_os_PerfettoTrackEventExtraCounterDouble_delete},
+         {"native_set_value", "(JD)V",
+          (void*)android_os_PerfettoTrackEventExtraCounterDouble_set_value},
+         {"native_get_extra_ptr", "(J)J",
+          (void*)android_os_PerfettoTrackEventExtraCounterDouble_get_extra_ptr}};
+
+int register_android_os_PerfettoTrackEventExtra(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$ArgInt64",
+                                       gArgInt64Methods, NELEM(gArgInt64Methods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register arg int64 native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$ArgBool",
+                                   gArgBoolMethods, NELEM(gArgBoolMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register arg bool native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$ArgDouble",
+                                   gArgDoubleMethods, NELEM(gArgDoubleMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register arg double native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$ArgString",
+                                   gArgStringMethods, NELEM(gArgStringMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register arg string native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$FieldInt64",
+                                   gFieldInt64Methods, NELEM(gFieldInt64Methods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register field int64 native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$FieldDouble",
+                                   gFieldDoubleMethods, NELEM(gFieldDoubleMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register field double native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$FieldString",
+                                   gFieldStringMethods, NELEM(gFieldStringMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register field string native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$FieldNested",
+                                   gFieldNestedMethods, NELEM(gFieldNestedMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register field nested native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra", gExtraMethods,
+                                   NELEM(gExtraMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register extra native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$Proto", gProtoMethods,
+                                   NELEM(gProtoMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register proto native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$Flow", gFlowMethods,
+                                   NELEM(gFlowMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register flow native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$NamedTrack",
+                                   gNamedTrackMethods, NELEM(gNamedTrackMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register named track native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$CounterTrack",
+                                   gCounterTrackMethods, NELEM(gCounterTrackMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register counter track native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$CounterInt64",
+                                   gCounterInt64Methods, NELEM(gCounterInt64Methods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register counter int64 native methods.");
+
+    res = jniRegisterNativeMethods(env, "android/os/PerfettoTrackEventExtra$CounterDouble",
+                                   gCounterDoubleMethods, NELEM(gCounterDoubleMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register counter double native methods.");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 8003bb7..639f5bf 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -1706,6 +1706,10 @@
     return res;
 }
 
+static jboolean android_os_BinderProxy_frozenStateChangeCallbackSupported(JNIEnv*, jclass*) {
+    return ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION);
+}
+
 static void BinderProxy_destroy(void* rawNativeData)
 {
     BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
@@ -1750,6 +1754,8 @@
         "(Landroid/os/IBinder$FrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback},
     {"removeFrozenStateChangeCallbackNative",
         "(Landroid/os/IBinder$FrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback},
+    {"isFrozenStateChangeCallbackSupportedNative",
+        "()Z", (void*)android_os_BinderProxy_frozenStateChangeCallbackSupported},
     {"getNativeFinalizer",  "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
     {"getExtension",        "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
 };
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index dc72539..67c9725 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -490,6 +490,28 @@
     return cpus;
 }
 
+jlongArray android_os_Process_getSchedAffinity(JNIEnv* env, jobject clazz, jint pid) {
+    // sched_getaffinity will do memset 0 for the unset bits within set_alloc_size_byte
+    cpu_set_t cpu_set;
+    if (sched_getaffinity(pid, sizeof(cpu_set_t), &cpu_set) != 0) {
+        signalExceptionForError(env, errno, pid);
+        return nullptr;
+    }
+    int cpu_cnt = std::min(CPU_SETSIZE, get_nprocs_conf());
+    int masks_len = (int)(CPU_ALLOC_SIZE(cpu_cnt) / sizeof(__CPU_BITTYPE));
+    jlongArray masks = env->NewLongArray(masks_len);
+    if (masks == nullptr) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+        return nullptr;
+    }
+    jlong* mask_elements = env->GetLongArrayElements(masks, 0);
+    for (int i = 0; i < masks_len; i++) {
+        mask_elements[i] = cpu_set.__bits[i];
+    }
+    env->ReleaseLongArrayElements(masks, mask_elements, 0);
+    return masks;
+}
+
 static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
     // Establishes the calling thread as illegal to put into the background.
     // Typically used only for the system process's main looper.
@@ -1370,6 +1392,7 @@
         {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
         {"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup},
         {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
+        {"getSchedAffinity", "(I)[J", (void*)android_os_Process_getSchedAffinity},
         {"setArgV0Native", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
         {"setUid", "(I)I", (void*)android_os_Process_setUid},
         {"setGid", "(I)I", (void*)android_os_Process_setGid},
diff --git a/core/jni/platform/darwin/libandroid_runtime_export.exp b/core/jni/platform/darwin/libandroid_runtime_export.exp
new file mode 100644
index 0000000..00a7585
--- /dev/null
+++ b/core/jni/platform/darwin/libandroid_runtime_export.exp
@@ -0,0 +1,38 @@
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# symbols needed for the JNI operations
+_JNI_OnLoad
+_ANativeWindow*
+
+# symbols needed to link with layoutlib_jni
+___android_log*
+__ZNK7android7RefBase*
+__ZN7android4base9SetLogger*
+__ZN7android4base10SetAborter*
+__ZN7android4base11GetProperty*
+__ZN7android4Rect*
+__ZN7android5Fence*
+__ZN7android7RefBase*
+__ZN7android7String*
+__ZN7android10VectorImpl*
+__ZN7android11BufferQueue*
+__ZN7android14AndroidRuntime*
+__ZN7android14sp_report_raceEv*
+__ZN7android15KeyCharacterMap*
+__ZN7android15InputDeviceInfo*
+__ZN7android31android_view_InputDevice_create*
+__ZN7android53android_view_Surface_createFromIGraphicBufferProducer*
diff --git a/core/jni/platform/linux/libandroid_runtime_export.txt b/core/jni/platform/linux/libandroid_runtime_export.txt
new file mode 100644
index 0000000..50e0b75
--- /dev/null
+++ b/core/jni/platform/linux/libandroid_runtime_export.txt
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+{
+  global:
+    # symbols needed for the JNI operations
+    JNI_OnLoad;
+    ANativeWindow*;
+
+    # symbols needed to link with layoutlib_jni
+    __android_log*;
+    _ZNK7android7RefBase*;
+    _ZN7android4base9SetLogger*;
+    _ZN7android4base10SetAborter*;
+    _ZN7android4base11GetProperty*;
+    _ZN7android4Rect*;
+    _ZN7android5Fence*;
+    _ZN7android7RefBase*;
+    _ZN7android7String*;
+    _ZN7android10VectorImpl*;
+    _ZN7android11BufferQueue*;
+    _ZN7android14AndroidRuntime*;
+    _ZN7android14sp_report_raceEv*;
+    _ZN7android15KeyCharacterMap*;
+    _ZN7android15InputDeviceInfo*;
+    _ZN7android31android_view_InputDevice_create*;
+    _ZN7android53android_view_Surface_createFromIGraphicBufferProducer*;
+
+    # symbols needed by Ravenwood to override system properties
+    __system_property_find;
+    __system_property_get;
+    __system_property_read_callback;
+    __system_property_set;
+  local:
+    *;
+};
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 7e9d623..c901ee1 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -567,6 +567,8 @@
     // value.
     optional SettingProto rtt_calling_mode = 69 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
+    optional SettingProto screen_off_udfps_enabled = 104 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
     message Screensaver {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
 
@@ -744,5 +746,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 104;
+    // Next tag = 105;
 }
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index e424e82..dd9bfa5 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -227,6 +227,7 @@
 
         optional SettingProto reverse_vertical_scrolling = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto swap_primary_button = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto scrolling_acceleration = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
 
     optional Mouse mouse = 38;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e133ca4..dc95471 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4559,7 +4559,8 @@
          @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ENABLE_LIMITED_VDM_ROLE)
     -->
     <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_SENSOR_DEVICE_STREAMING"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged"
+        android:featureFlag="android.companion.virtualdevice.flags.enable_limited_vdm_role" />
 
     <!-- Allows application to request to be associated with a vehicle head unit capable of
          automotive projection
@@ -8780,6 +8781,20 @@
                 android:featureFlag="com.android.art.flags.executable_method_file_offsets" />
 
     <!--
+        @SystemApi
+        @FlaggedApi(android.content.pm.Flags.FLAG_UID_BASED_PROVIDER_LOOKUP)
+        Allows an app to resolve components (e.g ContentProviders) on behalf of
+        other UIDs
+        <p>Protection level: signature|privileged
+        @hide
+   -->
+    <permission
+        android:name="android.permission.RESOLVE_COMPONENT_FOR_UID"
+        android:protectionLevel="signature|privileged"
+        android:featureFlag="android.content.pm.uid_based_provider_lookup" />
+    <uses-permission android:name="android.permission.RESOLVE_COMPONENT_FOR_UID" />
+
+    <!--
         @TestApi
         Signature permission reserved for testing. This should never be used to
         gate any actual functionality.
@@ -9164,15 +9179,6 @@
             </intent-filter>
         </receiver>
 
-        <receiver android:name="com.android.server.updates.CertificateTransparencyLogInstallReceiver"
-                android:exported="true"
-                android:permission="android.permission.UPDATE_CONFIG">
-            <intent-filter>
-                <action android:name="android.intent.action.UPDATE_CT_LOGS" />
-                <data android:scheme="content" android:host="*" android:mimeType="*/*" />
-            </intent-filter>
-        </receiver>
-
         <receiver android:name="com.android.server.updates.LangIdInstallReceiver"
                 android:exported="true"
                 android:permission="android.permission.UPDATE_CONFIG">
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/core/res/res/drawable/ic_notification_2025_collapse.xml
similarity index 61%
copy from packages/SystemUI/res/color/slider_active_track_color.xml
copy to core/res/res/drawable/ic_notification_2025_collapse.xml
index 8ba5e49..1b40c55 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/core/res/res/drawable/ic_notification_2025_collapse.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<!--
   ~ Copyright (C) 2024 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,13 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M480,432L296,616L240,560L480,320L720,560L664,616L480,432Z"/>
+</vector>
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/core/res/res/drawable/ic_notification_2025_expand.xml
similarity index 61%
copy from packages/SystemUI/res/color/slider_active_track_color.xml
copy to core/res/res/drawable/ic_notification_2025_expand.xml
index 8ba5e49..ea5e0f0 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/core/res/res/drawable/ic_notification_2025_expand.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<!--
   ~ Copyright (C) 2024 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,13 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+  <path
+      android:fillColor="@android:color/white"
+      android:pathData="M480,616L240,376L296,320L480,504L664,320L720,376L480,616Z"/>
+</vector>
diff --git a/core/res/res/drawable/notification_2025_expand_button_pill_bg.xml b/core/res/res/drawable/notification_2025_expand_button_pill_bg.xml
new file mode 100644
index 0000000..74f697a
--- /dev/null
+++ b/core/res/res/drawable/notification_2025_expand_button_pill_bg.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/expand_button_pill_colorized_layer">
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <corners android:radius="@dimen/notification_2025_expand_button_pill_height" />
+            <solid android:color="@android:color/white" />
+        </shape>
+    </item>
+    <item>
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <corners android:radius="@dimen/notification_2025_expand_button_pill_height" />
+            <solid android:color="@color/notification_expand_button_state_tint" />
+        </shape>
+    </item>
+</layer-list>
diff --git a/core/res/res/layout/notification_2025_expand_button.xml b/core/res/res/layout/notification_2025_expand_button.xml
new file mode 100644
index 0000000..c8263c2
--- /dev/null
+++ b/core/res/res/layout/notification_2025_expand_button.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!-- extends FrameLayout -->
+<com.android.internal.widget.NotificationExpandButton
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/expand_button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="top|end"
+    android:contentDescription="@string/expand_button_content_description_collapsed"
+    >
+
+    <LinearLayout
+        android:id="@+id/expand_button_pill"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/notification_2025_expand_button_pill_height"
+        android:minWidth="@dimen/notification_2025_expand_button_pill_width"
+        android:paddingVertical="@dimen/notification_2025_expand_button_vertical_icon_padding"
+        android:paddingHorizontal="@dimen/notification_2025_expand_button_horizontal_icon_padding"
+        android:orientation="horizontal"
+        android:background="@drawable/notification_2025_expand_button_pill_bg"
+        android:gravity="center"
+        android:layout_gravity="center_vertical"
+        android:duplicateParentState="true"
+        >
+
+        <TextView
+            android:id="@+id/expand_button_number"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Info"
+            android:gravity="center_vertical"
+            android:visibility="gone"
+            />
+
+        <ImageView
+            android:id="@+id/expand_button_icon"
+            android:layout_width="@dimen/notification_2025_expand_button_icon_size"
+            android:layout_height="@dimen/notification_2025_expand_button_icon_size"
+            android:scaleType="fitCenter"
+            android:importantForAccessibility="no"
+            />
+
+    </LinearLayout>
+
+</com.android.internal.widget.NotificationExpandButton>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_base.xml b/core/res/res/layout/notification_2025_template_collapsed_base.xml
index 76c810b..c827dcb 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_base.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_base.xml
@@ -157,39 +157,28 @@
             android:maxDrawableHeight="@dimen/notification_right_icon_size"
             />
 
-        <LinearLayout
-            android:id="@+id/notification_buttons_column"
+        <FrameLayout
+            android:id="@+id/expand_button_touch_container"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_alignParentEnd="true"
-            android:orientation="vertical"
+            android:minWidth="@dimen/notification_content_margin_end"
             >
 
-            <include layout="@layout/notification_close_button"
-                android:layout_width="@dimen/notification_close_button_size"
-                android:layout_height="@dimen/notification_close_button_size"
-                android:layout_gravity="end"
-                android:layout_marginEnd="20dp"
+            <include layout="@layout/notification_2025_expand_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="top|end"
+                android:layout_margin="@dimen/notification_2025_margin"
                 />
 
-            <FrameLayout
-                android:id="@+id/expand_button_touch_container"
-                android:layout_width="wrap_content"
-                android:layout_height="0dp"
-                android:layout_weight="1"
-                android:minWidth="@dimen/notification_content_margin_end"
-                >
-
-                <include layout="@layout/notification_expand_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical|end"
-                    />
-
-            </FrameLayout>
-
-        </LinearLayout>
+        </FrameLayout>
 
     </LinearLayout>
 
+    <include layout="@layout/notification_close_button"
+        android:id="@+id/close_button"
+        android:layout_width="@dimen/notification_close_button_size"
+        android:layout_height="@dimen/notification_close_button_size"
+        android:layout_gravity="top|end" />
+
 </FrameLayout>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_call.xml b/core/res/res/layout/notification_2025_template_collapsed_call.xml
index c4bca11..ce38c164 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_call.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_call.xml
@@ -66,10 +66,11 @@
             >
 
             <include
-                layout="@layout/notification_expand_button"
+                layout="@layout/notification_2025_expand_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
+                android:layout_gravity="top|end"
+                android:layout_margin="@dimen/notification_2025_margin"
                 />
 
         </FrameLayout>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_media.xml b/core/res/res/layout/notification_2025_template_collapsed_media.xml
index 2e0a7af..0021b83 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_media.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_media.xml
@@ -185,13 +185,21 @@
             android:minWidth="@dimen/notification_content_margin_end"
             >
 
-            <include layout="@layout/notification_expand_button"
+            <include layout="@layout/notification_2025_expand_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical|end"
+                android:layout_gravity="top|end"
+                android:layout_margin="@dimen/notification_2025_margin"
                 />
 
         </FrameLayout>
 
     </LinearLayout>
+
+    <include layout="@layout/notification_close_button"
+        android:id="@+id/close_button"
+        android:layout_width="@dimen/notification_close_button_size"
+        android:layout_height="@dimen/notification_close_button_size"
+        android:layout_gravity="top|end" />
+
 </com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
index f644ade..f3e4ce1 100644
--- a/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_collapsed_messaging.xml
@@ -189,16 +189,23 @@
                     android:minWidth="@dimen/notification_content_margin_end"
                     >
 
-                    <include layout="@layout/notification_expand_button"
+                    <include layout="@layout/notification_2025_expand_button"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:layout_gravity="center_vertical|end"
+                        android:layout_gravity="top|end"
+                        android:layout_margin="@dimen/notification_2025_margin"
                         />
 
                 </FrameLayout>
 
             </LinearLayout>
 
+            <include layout="@layout/notification_close_button"
+                android:id="@+id/close_button"
+                android:layout_width="@dimen/notification_close_button_size"
+                android:layout_height="@dimen/notification_close_button_size"
+                android:layout_gravity="top|end" />
+
         </com.android.internal.widget.NotificationMaxHeightFrameLayout>
 
     <LinearLayout
diff --git a/core/res/res/layout/notification_2025_template_conversation.xml b/core/res/res/layout/notification_2025_template_conversation.xml
index f31f65e..6be5a1c 100644
--- a/core/res/res/layout/notification_2025_template_conversation.xml
+++ b/core/res/res/layout/notification_2025_template_conversation.xml
@@ -148,10 +148,11 @@
                     android:clipToPadding="false"
                     android:clipChildren="false"
                     />
-                <include layout="@layout/notification_expand_button"
+                <include layout="@layout/notification_2025_expand_button"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_gravity="center"
+                    android:layout_gravity="top|end"
+                    android:layout_margin="@dimen/notification_2025_margin"
                     />
             </LinearLayout>
         </LinearLayout>
diff --git a/core/res/res/layout/notification_2025_template_expanded_base.xml b/core/res/res/layout/notification_2025_template_expanded_base.xml
index e480fe5..d364c65 100644
--- a/core/res/res/layout/notification_2025_template_expanded_base.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_base.xml
@@ -40,13 +40,14 @@
 
             <include layout="@layout/notification_2025_template_header" />
 
+            <!-- Note: the top margin is being set in code based on the estimated space needed for
+            the header text. -->
             <LinearLayout
                 android:id="@+id/notification_main_column"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="@dimen/notification_2025_content_margin_start"
                 android:layout_marginEnd="@dimen/notification_content_margin_end"
-                android:layout_marginTop="@dimen/notification_content_margin_top"
                 android:orientation="vertical"
                 >
 
diff --git a/core/res/res/layout/notification_2025_template_expanded_big_picture.xml b/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
index 18bafe0..12e1172 100644
--- a/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_big_picture.xml
@@ -32,11 +32,12 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_gravity="top"
-        android:layout_marginTop="@dimen/notification_content_margin_top"
         android:clipToPadding="false"
         android:orientation="vertical"
         >
 
+        <!-- Note: the top margin is being set in code based on the estimated space needed for
+        the header text. -->
         <LinearLayout
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_2025_template_expanded_big_text.xml b/core/res/res/layout/notification_2025_template_expanded_big_text.xml
index 9ff141b..c9dd868 100644
--- a/core/res/res/layout/notification_2025_template_expanded_big_text.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_big_text.xml
@@ -30,12 +30,13 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="top"
-        android:layout_marginTop="@dimen/notification_content_margin_top"
         android:layout_marginBottom="@dimen/notification_content_margin"
         android:clipToPadding="false"
         android:orientation="vertical"
         >
 
+        <!-- Note: the top margin is being set in code based on the estimated space needed for
+        the header text. -->
         <com.android.internal.widget.RemeasuringLinearLayout
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_2025_template_expanded_call.xml b/core/res/res/layout/notification_2025_template_expanded_call.xml
index 2af0ec2..0be6125 100644
--- a/core/res/res/layout/notification_2025_template_expanded_call.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_call.xml
@@ -48,8 +48,8 @@
                 android:id="@+id/notification_main_column"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_weight="1"
                 android:layout_marginStart="@dimen/notification_2025_content_margin_start"
+                android:layout_weight="1"
                 android:orientation="vertical"
                 android:minHeight="68dp"
                 >
diff --git a/core/res/res/layout/notification_2025_template_expanded_inbox.xml b/core/res/res/layout/notification_2025_template_expanded_inbox.xml
index 9fb44ccc..8434b36 100644
--- a/core/res/res/layout/notification_2025_template_expanded_inbox.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_inbox.xml
@@ -28,10 +28,11 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="top"
-            android:layout_marginTop="@dimen/notification_content_margin_top"
             android:clipToPadding="false"
             android:orientation="vertical">
 
+        <!-- Note: the top margin is being set in code based on the estimated space needed for
+        the header text. -->
         <LinearLayout
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_2025_template_expanded_media.xml b/core/res/res/layout/notification_2025_template_expanded_media.xml
index 578a0b2..e90ab79 100644
--- a/core/res/res/layout/notification_2025_template_expanded_media.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_media.xml
@@ -34,11 +34,12 @@
         android:id="@+id/notification_media_content"
         >
 
+        <!-- Note: the top margin is being set in code based on the estimated space needed for
+        the header text. -->
         <LinearLayout
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/notification_content_margin_top"
             android:layout_marginStart="@dimen/notification_2025_content_margin_start"
             android:layout_marginEnd="@dimen/notification_content_margin_end"
             android:orientation="vertical"
diff --git a/core/res/res/layout/notification_2025_template_expanded_messaging.xml b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
index e3c2014..7f5a36b 100644
--- a/core/res/res/layout/notification_2025_template_expanded_messaging.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_messaging.xml
@@ -33,10 +33,11 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="top"
-            android:layout_marginTop="@dimen/notification_2025_header_height"
             android:clipChildren="false"
             android:orientation="vertical">
 
+        <!-- Note: the top margin is being set in code based on the estimated space needed for
+        the header text. -->
         <com.android.internal.widget.RemeasuringLinearLayout
             android:id="@+id/notification_main_column"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_2025_template_expanded_progress.xml b/core/res/res/layout/notification_2025_template_expanded_progress.xml
index afa4bc6..5d4fc4c 100644
--- a/core/res/res/layout/notification_2025_template_expanded_progress.xml
+++ b/core/res/res/layout/notification_2025_template_expanded_progress.xml
@@ -41,13 +41,14 @@
 
             <include layout="@layout/notification_2025_template_header" />
 
+            <!-- Note: the top margin is being set in code based on the estimated space needed for
+            the header text. -->
             <LinearLayout
                 android:id="@+id/notification_main_column"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="@dimen/notification_2025_content_margin_start"
                 android:layout_marginEnd="@dimen/notification_content_margin_end"
-                android:layout_marginTop="@dimen/notification_content_margin_top"
                 android:orientation="vertical"
                 >
 
diff --git a/core/res/res/layout/notification_2025_template_header.xml b/core/res/res/layout/notification_2025_template_header.xml
index fc727e1..3f34eb3 100644
--- a/core/res/res/layout/notification_2025_template_header.xml
+++ b/core/res/res/layout/notification_2025_template_header.xml
@@ -57,11 +57,11 @@
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/notification_top_line"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:layout_alignParentStart="true"
-        android:layout_centerVertical="true"
-        android:layout_toStartOf="@id/notification_buttons_column"
+        android:layout_toStartOf="@id/expand_button"
         android:layout_alignWithParentIfMissing="true"
+        android:layout_marginVertical="@dimen/notification_2025_margin"
         android:clipChildren="false"
         android:gravity="center_vertical"
         android:paddingStart="@dimen/notification_2025_content_margin_start"
@@ -81,28 +81,18 @@
         android:focusable="false"
         />
 
-    <LinearLayout
-        android:id="@+id/notification_buttons_column"
+    <include layout="@layout/notification_2025_expand_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentEnd="true"
-        android:orientation="vertical"
-        >
+        android:layout_gravity="top|end"
+        android:layout_margin="@dimen/notification_2025_margin"
+        android:layout_alignParentEnd="true" />
 
-        <include layout="@layout/notification_close_button"
-            android:layout_width="@dimen/notification_close_button_size"
-            android:layout_height="@dimen/notification_close_button_size"
-            android:layout_gravity="end"
-            android:layout_marginEnd="20dp"
-            />
-
-        <include layout="@layout/notification_expand_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentEnd="true"
-            android:layout_centerVertical="true"
-            />
-
-    </LinearLayout>
+    <include layout="@layout/notification_close_button"
+        android:id="@+id/close_button"
+        android:layout_width="@dimen/notification_close_button_size"
+        android:layout_height="@dimen/notification_close_button_size"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentEnd="true" />
 
 </NotificationHeaderView>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 3bb58a5..196f9ac 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1959,7 +1959,7 @@
     <string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"Nit entre setmana"</string>
     <string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Cap de setmana"</string>
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"Esdeveniment"</string>
-    <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Mentre dormo"</string>
+    <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Dormint"</string>
     <string name="zen_mode_implicit_name" msgid="177586786232302019">"No molestis (<xliff:g id="APP_NAME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_implicit_trigger_description" msgid="5714956693073007111">"Gestionat per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="zen_mode_implicit_activated" msgid="2634285680776672994">"Activat"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index ab3b66b..e470f0e 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -421,7 +421,7 @@
     <string name="permlab_runInBackground" msgid="541863968571682785">"exekutatu atzeko planoan"</string>
     <string name="permdesc_runInBackground" msgid="4344539472115495141">"Atzeko planoan exekuta liteke aplikazioa eta horrek bizkorrago agor lezake bateria."</string>
     <string name="permlab_useDataInBackground" msgid="783415807623038947">"erabili datuak atzeko planoan"</string>
-    <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Aplikazioak datuak erabil litzake atzeko planoan eta horrek datu-erabilera areago lezake."</string>
+    <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Datuak atzeko planoan erabil ditzake aplikazioak, eta baliteke horrek datu-erabilera handitzea."</string>
     <string name="permlab_schedule_exact_alarm" msgid="6683283918033029730">"antolatu ekintzak une zehatzetan gerta daitezen"</string>
     <string name="permdesc_schedule_exact_alarm" msgid="8198009212013211497">"Aplikazio honek ekintzak programa ditzake etorkizunean egin daitezen. Horrek esan nahi du gailua aktiboki erabiltzen ari ez zarenean ere exekuta daitekeela aplikazioa."</string>
     <string name="permlab_use_exact_alarm" msgid="348045139777131552">"antolatu alarmak edo gertaera-gogorarazpenak"</string>
@@ -698,7 +698,7 @@
     <string name="fingerprint_or_screen_lock_dialog_default_subtitle" msgid="5195808203117992200">"Aurrera egiteko, erabili hatz-marka edo pantailaren blokeoa"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Arazo bat izan da. Saiatu berriro."</string>
+    <string name="fingerprint_error_vendor_unknown" msgid="4170002184907291065">"Arazoren bat izan da. Saiatu berriro."</string>
     <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Hatz-markaren ikonoa"</string>
     <string name="device_unlock_notification_name" msgid="2632928999862915709">"Gailua desblokeatzea"</string>
     <string name="alternative_unlock_setup_notification_title" msgid="6241508547901933544">"Probatu gailua desblokeatzeko beste modu bat"</string>
@@ -759,7 +759,7 @@
     <string name="face_or_screen_lock_dialog_default_subtitle" msgid="5006381531158341844">"Aurrera egiteko, erabili aurpegia edo pantailaren blokeoa"</string>
   <string-array name="face_error_vendor">
   </string-array>
-    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Arazo bat izan da. Saiatu berriro."</string>
+    <string name="face_error_vendor_unknown" msgid="7387005932083302070">"Arazoren bat izan da. Saiatu berriro."</string>
     <string name="face_icon_content_description" msgid="465030547475916280">"Aurpegiaren ikonoa"</string>
     <string name="permlab_readSyncSettings" msgid="6250532864893156277">"irakurri sinkronizazio-ezarpenak"</string>
     <string name="permdesc_readSyncSettings" msgid="1325658466358779298">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen dio aplikazioari. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 1f30da3..b626194 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1049,7 +1049,7 @@
     <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"За да го отклучите, најавете се со вашата сметка на Google."</string>
     <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"Корисничко име (e-пошта)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Лозинка"</string>
-    <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Најави се"</string>
+    <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Најавете се"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"Неважечко корисничко име или лозинка."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"Го заборави своето корисничко име или лозинката?\nПосети"<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"Се проверува..."</string>
@@ -1723,7 +1723,7 @@
     <string name="kg_login_instructions" msgid="3619844310339066827">"За да го отклучите, најавете се со вашата сметка на Google."</string>
     <string name="kg_login_username_hint" msgid="1765453775467133251">"Корисничко име (е-пошта)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"Лозинка"</string>
-    <string name="kg_login_submit_button" msgid="893611277617096870">"Најави се"</string>
+    <string name="kg_login_submit_button" msgid="893611277617096870">"Најавете се"</string>
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"Неважечко корисничко име или лозинка."</string>
     <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Го заборави своето корисничко име или лозинката?\nПосети"<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="4676010303243317253">"Сметката се проверува..."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e7e96f5..2cadf4b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -288,7 +288,7 @@
     <string name="global_action_settings" msgid="4671878836947494217">"Nastavitve"</string>
     <string name="global_action_assist" msgid="2517047220311505805">"Pomoč"</string>
     <string name="global_action_voice_assist" msgid="6655788068555086695">"Glas. pomočnik"</string>
-    <string name="global_action_lockdown" msgid="2475471405907902963">"Zakleni"</string>
+    <string name="global_action_lockdown" msgid="2475471405907902963">"Zaklep"</string>
     <string name="status_bar_notification_info_overflow" msgid="3330152558746563475">"999 +"</string>
     <string name="notification_compact_heads_up_reply" msgid="2425293958371284340">"Odgovori"</string>
     <string name="notification_hidden_text" msgid="2835519769868187223">"Novo obvestilo"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c2be30e..2b97029 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1273,7 +1273,7 @@
     <string name="aerr_application_repeated" msgid="7804378743218496566">"<xliff:g id="APPLICATION">%1$s</xliff:g> పునరావృతంగా ఆపివేయబడుతోంది"</string>
     <string name="aerr_process_repeated" msgid="1153152413537954974">"<xliff:g id="PROCESS">%1$s</xliff:g> పునరావృతంగా ఆపివేయబడుతోంది"</string>
     <string name="aerr_restart" msgid="2789618625210505419">"యాప్‌ను మళ్లీ తెరువు"</string>
-    <string name="aerr_report" msgid="3095644466849299308">"ఫీడ్‌బ్యాక్‌ను పంపు"</string>
+    <string name="aerr_report" msgid="3095644466849299308">"ఫీడ్‌బ్యాక్‌ను పంపండి"</string>
     <string name="aerr_close" msgid="3398336821267021852">"మూసివేయండి"</string>
     <string name="aerr_mute" msgid="2304972923480211376">"పరికరం పునఃప్రారంభమయ్యే వరకు మ్యూట్ చేయి"</string>
     <string name="aerr_wait" msgid="3198677780474548217">"వేచి ఉండండి"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index e28b646..e6295ea 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -100,4 +100,7 @@
     <!-- Whether to enable scaling and fading animation to scrollviews while scrolling.
          P.S this is a change only intended for wear devices. -->
     <bool name="config_enableViewGroupScalingFading">true</bool>
+
+    <!-- Allow the gesture to double tap the power button to trigger a target action. -->
+    <bool name="config_doubleTapPowerGestureEnabled">false</bool>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 565e28e..45a5d85 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2165,6 +2165,17 @@
          config_enableGeofenceOverlay is false. -->
     <string name="config_geofenceProviderPackageName" translatable="false">@null</string>
 
+    <!-- Whether to enable GNSS assistance overlay which allows GnssAssistanceProvider to be
+     replaced by an app at run-time. When disabled, only the
+     config_gnssAssistanceProviderPackageName package will be searched for
+     GnssAssistanceProvider, otherwise any system package is eligible. Anyone who wants to
+     disable the overlay mechanism can set it to false.
+     -->
+    <bool name="config_enableGnssAssistanceOverlay" translatable="false">true</bool>
+    <!-- Package name providing GNSS assistance API support. Used only when
+         config_enableGnssAssistanceOverlay is false. -->
+    <string name="config_gnssAssistanceProviderPackageName" translatable="false">@null</string>
+
     <!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware
          Activity-Recognition to be replaced by an app at run-time. When disabled, only the
          config_activityRecognitionHardwarePackageName package will be searched for
diff --git a/core/res/res/values/config_watch.xml b/core/res/res/values/config_watch.xml
index 629a343..bcb1e09 100644
--- a/core/res/res/values/config_watch.xml
+++ b/core/res/res/values/config_watch.xml
@@ -15,8 +15,7 @@
   -->
 
 <resources>
-    <!--  TODO(b/382103556): use predefined Material3 token  -->
     <!-- For Wear Material3 -->
-    <dimen name="config_wearMaterial3_buttonCornerRadius">26dp</dimen>
-    <dimen name="config_wearMaterial3_bottomDialogCornerRadius">18dp</dimen>
+    <dimen name="config_wearMaterial3_buttonCornerRadius">@dimen/config_shapeCornerRadiusLarge</dimen>
+    <dimen name="config_wearMaterial3_bottomDialogCornerRadius">@dimen/config_shapeCornerRadiusMedium</dimen>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index fb21c75..a4735fe 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -310,9 +310,15 @@
     <!-- Size of the stroke with for the emphasized notification button style -->
     <dimen name="emphasized_button_stroke_width">1dp</dimen>
 
-    <!-- height of the content margin to accomodate for the header -->
+    <!-- height of the content margin to accommodate for the header -->
     <dimen name="notification_content_margin_top">50dp</dimen>
 
+    <!-- The spacing between the content and the header text above it, scaling with text size.
+         This value is chosen so that, taking into account the text spacing for both the text in the
+         top line and the text in the content, the distance between them is 4dp with the default
+         screen configuration (and will grow accordingly for larger font sizes) -->
+    <dimen name="notification_2025_content_margin_top">10sp</dimen>
+
     <!-- height of the content margin that is applied at the end of the notification content -->
     <dimen name="notification_content_margin">20dp</dimen>
 
@@ -384,9 +390,24 @@
     <!-- the height of the expand button pill -->
     <dimen name="notification_expand_button_pill_height">24dp</dimen>
 
+    <!-- the height of the expand button pill (2025 redesign version) -->
+    <dimen name="notification_2025_expand_button_pill_height">20dp</dimen>
+
+    <!-- the width of the expand button pill (2025 redesign version) -->
+    <dimen name="notification_2025_expand_button_pill_width">28dp</dimen>
+
+    <!-- the size of the expand arrow (2025 redesign version) -->
+    <dimen name="notification_2025_expand_button_icon_size">16sp</dimen>
+
     <!-- the padding of the expand icon in the notification header -->
     <dimen name="notification_expand_button_icon_padding">2dp</dimen>
 
+    <!-- the padding of the expand icon in the notification header -->
+    <dimen name="notification_2025_expand_button_vertical_icon_padding">2dp</dimen>
+
+    <!-- the padding of the expand icon in the notification header -->
+    <dimen name="notification_2025_expand_button_horizontal_icon_padding">6dp</dimen>
+
     <!-- the size of the notification close button -->
     <dimen name="notification_close_button_size">16dp</dimen>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cfc3ddc..33d3858 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -246,6 +246,8 @@
     <string name="NetworkPreferenceSwitchSummary">Try changing preferred network. Tap to change.</string>
     <!-- Displayed to tell the user that emergency calls might not be available. -->
     <string name="EmergencyCallWarningTitle">Emergency calling unavailable</string>
+    <!-- Displayed to tell the user that the notification can be permanently turned off -->
+    <string name="emergency_calling_do_not_show_again">Do Not Show Again</string>
     <!-- Displayed to tell the user that emergency calls might not be available; this is shown to
          the user when only WiFi calling is available and the carrier does not support emergency
          calls over WiFi calling. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 73e06f6..6ee2839 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -640,6 +640,7 @@
   <java-symbol type="string" name="auto_data_switch_title" />
   <java-symbol type="string" name="auto_data_switch_content" />
   <java-symbol type="string" name="RestrictedStateContentMsimTemplate" />
+  <java-symbol type="string" name="emergency_calling_do_not_show_again" />
   <java-symbol type="string" name="notification_channel_network_alert" />
   <java-symbol type="string" name="notification_channel_call_forward" />
   <java-symbol type="string" name="notification_channel_emergency_callback" />
@@ -2040,6 +2041,7 @@
   <java-symbol type="bool" name="config_useGnssHardwareProvider" />
   <java-symbol type="bool" name="config_enableGeocoderOverlay" />
   <java-symbol type="bool" name="config_enableGeofenceOverlay" />
+  <java-symbol type="bool" name="config_enableGnssAssistanceOverlay" />
   <java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
   <java-symbol type="bool" name="config_sf_limitedAlpha" />
   <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
@@ -2223,6 +2225,7 @@
   <java-symbol type="string" name="config_gnssLocationProviderPackageName" />
   <java-symbol type="string" name="config_geocoderProviderPackageName" />
   <java-symbol type="string" name="config_geofenceProviderPackageName" />
+  <java-symbol type="string" name="config_gnssAssistanceProviderPackageName" />
   <java-symbol type="string" name="config_networkLocationProviderPackageName" />
   <java-symbol type="string" name="config_wimaxManagerClassname" />
   <java-symbol type="string" name="config_wimaxNativeLibLocation" />
@@ -3227,6 +3230,8 @@
   <java-symbol type="id" name="header_text_divider" />
   <java-symbol type="id" name="header_text_secondary_divider" />
   <java-symbol type="drawable" name="ic_expand_notification" />
+  <java-symbol type="drawable" name="ic_notification_2025_collapse" />
+  <java-symbol type="drawable" name="ic_notification_2025_expand" />
   <java-symbol type="drawable" name="ic_collapse_notification" />
   <java-symbol type="drawable" name="notification_close_button_icon" />
   <java-symbol type="drawable" name="ic_expand_bundle" />
@@ -3239,6 +3244,8 @@
   <java-symbol type="dimen" name="notification_heading_margin_end" />
   <java-symbol type="dimen" name="notification_content_margin_top" />
   <java-symbol type="dimen" name="notification_content_margin" />
+  <java-symbol type="dimen" name="notification_2025_margin" />
+  <java-symbol type="dimen" name="notification_2025_content_margin_top" />
   <java-symbol type="dimen" name="notification_progress_margin_horizontal" />
   <java-symbol type="dimen" name="notification_header_background_height" />
   <java-symbol type="dimen" name="notification_header_touchable_height" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index c67a0f9..3ef3dfd 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -119,6 +119,7 @@
         "android.view.flags-aconfig-java",
     ],
     jni_libs: [
+        "libperfetto_trace_test_jni",
         "libpowermanagertest_jni",
         "libviewRootImplTest_jni",
         "libworksourceparceltest_jni",
@@ -260,6 +261,7 @@
         "compatibility-device-util-axt-ravenwood",
         "flag-junit",
         "platform-test-annotations",
+        "perfetto_trace_java_protos",
         "flag-junit",
         "testng",
     ],
diff --git a/core/tests/coretests/jni/Android.bp b/core/tests/coretests/jni/Android.bp
index d6379ca..798ec90 100644
--- a/core/tests/coretests/jni/Android.bp
+++ b/core/tests/coretests/jni/Android.bp
@@ -111,3 +111,27 @@
     ],
     gtest: false,
 }
+
+cc_test_library {
+    name: "libperfetto_trace_test_jni",
+    srcs: [
+        "PerfettoTraceTest.cpp",
+    ],
+    static_libs: [
+        "perfetto_trace_protos",
+        "libtracing_perfetto_test_utils",
+    ],
+    shared_libs: [
+        "liblog",
+        "libnativehelper",
+        "libperfetto_c",
+        "libprotobuf-cpp-lite",
+        "libtracing_perfetto",
+    ],
+    stl: "libc++_static",
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    gtest: false,
+}
diff --git a/core/tests/coretests/jni/PerfettoTraceTest.cpp b/core/tests/coretests/jni/PerfettoTraceTest.cpp
new file mode 100644
index 0000000..41d02ed7
--- /dev/null
+++ b/core/tests/coretests/jni/PerfettoTraceTest.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "PerfettoTraceTest"
+
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+
+#include "jni.h"
+#include "perfetto/public/abi/data_source_abi.h"
+#include "perfetto/public/abi/heap_buffer.h"
+#include "perfetto/public/abi/pb_decoder_abi.h"
+#include "perfetto/public/abi/tracing_session_abi.h"
+#include "perfetto/public/abi/track_event_abi.h"
+#include "perfetto/public/compiler.h"
+#include "perfetto/public/data_source.h"
+#include "perfetto/public/pb_decoder.h"
+#include "perfetto/public/producer.h"
+#include "perfetto/public/protos/config/trace_config.pzc.h"
+#include "perfetto/public/protos/trace/interned_data/interned_data.pzc.h"
+#include "perfetto/public/protos/trace/test_event.pzc.h"
+#include "perfetto/public/protos/trace/trace.pzc.h"
+#include "perfetto/public/protos/trace/trace_packet.pzc.h"
+#include "perfetto/public/protos/trace/track_event/debug_annotation.pzc.h"
+#include "perfetto/public/protos/trace/track_event/track_descriptor.pzc.h"
+#include "perfetto/public/protos/trace/track_event/track_event.pzc.h"
+#include "perfetto/public/protos/trace/trigger.pzc.h"
+#include "perfetto/public/te_category_macros.h"
+#include "perfetto/public/te_macros.h"
+#include "perfetto/public/track_event.h"
+#include "protos/perfetto/trace/interned_data/interned_data.pb.h"
+#include "protos/perfetto/trace/trace.pb.h"
+#include "protos/perfetto/trace/trace_packet.pb.h"
+#include "tracing_perfetto.h"
+#include "utils.h"
+
+namespace android {
+using ::perfetto::protos::EventCategory;
+using ::perfetto::protos::EventName;
+using ::perfetto::protos::FtraceEvent;
+using ::perfetto::protos::FtraceEventBundle;
+using ::perfetto::protos::InternedData;
+using ::perfetto::protos::Trace;
+using ::perfetto::protos::TracePacket;
+
+using ::perfetto::shlib::test_utils::TracingSession;
+
+struct TracingSessionHolder {
+    TracingSession tracing_session;
+};
+
+static void nativeRegisterPerfetto([[maybe_unused]] JNIEnv* env, jclass /* obj */) {
+    tracing_perfetto::registerWithPerfetto(false /* test */);
+}
+
+static jlong nativeStartTracing(JNIEnv* env, jclass /* obj */, jbyteArray configBytes) {
+    jsize length = env->GetArrayLength(configBytes);
+    std::vector<uint8_t> data;
+    data.reserve(length);
+    env->GetByteArrayRegion(configBytes, 0, length, reinterpret_cast<jbyte*>(data.data()));
+
+    TracingSession session = TracingSession::FromBytes(data.data(), length);
+    TracingSessionHolder* holder = new TracingSessionHolder(std::move(session));
+
+    return reinterpret_cast<long>(holder);
+}
+
+static jbyteArray nativeStopTracing([[maybe_unused]] JNIEnv* env, jclass /* obj */, jlong ptr) {
+    TracingSessionHolder* holder = reinterpret_cast<TracingSessionHolder*>(ptr);
+
+    // Stop
+    holder->tracing_session.FlushBlocking(5000);
+    holder->tracing_session.StopBlocking();
+
+    std::vector<uint8_t> data = holder->tracing_session.ReadBlocking();
+
+    delete holder;
+
+    jbyteArray bytes = env->NewByteArray(data.size());
+    env->SetByteArrayRegion(bytes, 0, data.size(), reinterpret_cast<jbyte*>(data.data()));
+    return bytes;
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) {
+    JNIEnv* env;
+    const JNINativeMethod methodTable[] = {/* name, signature, funcPtr */
+                                           {"nativeStartTracing", "([B)J",
+                                            (void*)nativeStartTracing},
+                                           {"nativeStopTracing", "(J)[B", (void*)nativeStopTracing},
+                                           {"nativeRegisterPerfetto", "()V",
+                                            (void*)nativeRegisterPerfetto}};
+
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    jniRegisterNativeMethods(env, "android/os/PerfettoTraceTest", methodTable,
+                             sizeof(methodTable) / sizeof(JNINativeMethod));
+
+    return JNI_VERSION_1_6;
+}
+
+} /* namespace android */
diff --git a/core/tests/coretests/res/color/color_with_lstar.xml b/core/tests/coretests/res/color/color_with_lstar.xml
index dcc3d6d..7762fc0 100644
--- a/core/tests/coretests/res/color/color_with_lstar.xml
+++ b/core/tests/coretests/res/color/color_with_lstar.xml
@@ -16,5 +16,5 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="#ff0000" android:lStar="50" />
+    <item android:color="@color/testcolor2" android:lStar="50" />
 </selector>
diff --git a/core/tests/coretests/res/values/colors.xml b/core/tests/coretests/res/values/colors.xml
index 029aa0d..f01af84 100644
--- a/core/tests/coretests/res/values/colors.xml
+++ b/core/tests/coretests/res/values/colors.xml
@@ -25,6 +25,5 @@
     <drawable name="yellow">#ffffff00</drawable>
     <color name="testcolor1">#ff00ff00</color>
     <color name="testcolor2">#ffff0000</color>
-    <color name="testcolor3">#fff00000</color>
     <color name="failColor">#ff0000ff</color>
 </resources>
diff --git a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
index cf6266c..931d646 100644
--- a/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
+++ b/core/tests/coretests/src/android/app/BackgroundStartPrivilegesTest.java
@@ -119,4 +119,15 @@
                 Arrays.asList(BSP_ALLOW_A, BSP_ALLOW_A, BSP_ALLOW_A, BSP_ALLOW_A)))
                 .isEqualTo(BSP_ALLOW_A);
     }
+
+    @Test
+    public void backgroundStartPrivilege_equals_works() {
+        assertThat(NONE).isEqualTo(NONE);
+        assertThat(ALLOW_BAL).isEqualTo(ALLOW_BAL);
+        assertThat(ALLOW_FGS).isEqualTo(ALLOW_FGS);
+        assertThat(BSP_ALLOW_A).isEqualTo(BSP_ALLOW_A);
+        assertThat(NONE).isNotEqualTo(ALLOW_BAL);
+        assertThat(ALLOW_FGS).isNotEqualTo(ALLOW_BAL);
+        assertThat(BSP_ALLOW_A).isNotEqualTo(BSP_ALLOW_B);
+    }
 }
diff --git a/core/tests/coretests/src/android/app/NotificationManagerTest.java b/core/tests/coretests/src/android/app/NotificationManagerTest.java
index 3213abe..6538ce8 100644
--- a/core/tests/coretests/src/android/app/NotificationManagerTest.java
+++ b/core/tests/coretests/src/android/app/NotificationManagerTest.java
@@ -18,8 +18,11 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -67,6 +70,8 @@
             mClock.advanceByMillis(5);
         }
 
+        verify(mNotificationManager.mBackendService, atLeast(20)).enqueueNotificationWithTag(any(),
+                any(), any(), anyInt(), any(), anyInt());
         verify(mNotificationManager.mBackendService, atMost(30)).enqueueNotificationWithTag(any(),
                 any(), any(), anyInt(), any(), anyInt());
     }
@@ -101,7 +106,54 @@
 
     @Test
     @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
-    public void notify_rapidAddAndCancel_isNotThrottled() throws Exception {
+    public void notifyAsPackage_rapidUpdate_isThrottled() throws Exception {
+        Notification n = exampleNotification();
+
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.notifyAsPackage("some.package.name", "tag", 1, n);
+            mClock.advanceByMillis(5);
+        }
+
+        verify(mNotificationManager.mBackendService, atLeast(20)).enqueueNotificationWithTag(
+                eq("some.package.name"), any(), any(), anyInt(), any(), anyInt());
+        verify(mNotificationManager.mBackendService, atMost(30)).enqueueNotificationWithTag(
+                eq("some.package.name"), any(), any(), anyInt(), any(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void cancel_unnecessaryAndRapid_isThrottled() throws Exception {
+
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.cancel(1);
+            mClock.advanceByMillis(5);
+        }
+
+        verify(mNotificationManager.mBackendService, atLeast(20)).cancelNotificationWithTag(any(),
+                any(), any(), anyInt(), anyInt());
+        verify(mNotificationManager.mBackendService, atMost(30)).cancelNotificationWithTag(any(),
+                any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void cancel_unnecessaryButReasonable_isNotThrottled() throws Exception {
+        // Scenario: the app tries to repeatedly cancel a single notification, but at a reasonable
+        // rate. Strange, but not what we're trying to block with NM_BINDER_PERF_THROTTLE_NOTIFY.
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.cancel(1);
+            mClock.advanceByMillis(500);
+        }
+
+        verify(mNotificationManager.mBackendService, times(100)).cancelNotificationWithTag(any(),
+                any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void cancel_necessaryAndRapid_isNotThrottled() throws Exception {
+        // Scenario: the app posts and immediately cancels a bunch of notifications. Strange,
+        // but not what we're trying to block with NM_BINDER_PERF_THROTTLE_NOTIFY.
         Notification n = exampleNotification();
 
         for (int i = 0; i < 100; i++) {
@@ -112,6 +164,83 @@
 
         verify(mNotificationManager.mBackendService, times(100)).enqueueNotificationWithTag(any(),
                 any(), any(), anyInt(), any(), anyInt());
+        verify(mNotificationManager.mBackendService, times(100)).cancelNotificationWithTag(any(),
+                any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void cancel_maybeNecessaryAndRapid_isNotThrottled() throws Exception {
+        // Scenario: the app posted a lot of notifications, is killed, then restarts (so NM client
+        // doesn't know about them), then cancels them one by one. We don't want to throttle this
+        // case.
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.cancel(i);
+            mClock.advanceByMillis(1);
+        }
+
+        verify(mNotificationManager.mBackendService, times(100)).cancelNotificationWithTag(any(),
+                any(), any(), anyInt(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void enqueue_afterCancel_isNotUpdateAndIsNotThrottled() throws Exception {
+        // First, hit the enqueue threshold.
+        Notification n = exampleNotification();
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.notify(1, n);
+            mClock.advanceByMillis(1);
+        }
+        verify(mNotificationManager.mBackendService, atMost(30)).enqueueNotificationWithTag(any(),
+                any(), any(), anyInt(), any(), anyInt());
+        reset(mNotificationManager.mBackendService);
+
+        // Now cancel that notification and then post it again. That should work.
+        mNotificationManager.cancel(1);
+        mNotificationManager.notify(1, n);
+        verify(mNotificationManager.mBackendService).enqueueNotificationWithTag(any(), any(), any(),
+                anyInt(), any(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void enqueue_afterCancelAsPackage_isNotUpdateAndIsNotThrottled() throws Exception {
+        // First, hit the enqueue threshold.
+        Notification n = exampleNotification();
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.notify(1, n);
+            mClock.advanceByMillis(1);
+        }
+        verify(mNotificationManager.mBackendService, atMost(30)).enqueueNotificationWithTag(any(),
+                any(), any(), anyInt(), any(), anyInt());
+        reset(mNotificationManager.mBackendService);
+
+        // Now cancel that notification and then post it again. That should work.
+        mNotificationManager.cancelAsPackage(mContext.getPackageName(), /* tag= */ null, 1);
+        mNotificationManager.notify(1, n);
+        verify(mNotificationManager.mBackendService).enqueueNotificationWithTag(any(), any(), any(),
+                anyInt(), any(), anyInt());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_NM_BINDER_PERF_THROTTLE_NOTIFY)
+    public void enqueue_afterCancelAll_isNotUpdateAndIsNotThrottled() throws Exception {
+        // First, hit the enqueue threshold.
+        Notification n = exampleNotification();
+        for (int i = 0; i < 100; i++) {
+            mNotificationManager.notify(1, n);
+            mClock.advanceByMillis(1);
+        }
+        verify(mNotificationManager.mBackendService, atMost(30)).enqueueNotificationWithTag(any(),
+                any(), any(), anyInt(), any(), anyInt());
+        reset(mNotificationManager.mBackendService);
+
+        // Now cancel all notifications and then post it again. That should work.
+        mNotificationManager.cancelAll();
+        mNotificationManager.notify(1, n);
+        verify(mNotificationManager.mBackendService).enqueueNotificationWithTag(any(), any(), any(),
+                anyInt(), any(), anyInt());
     }
 
     private Notification exampleNotification() {
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 9effeec..ca6ad6f 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -105,6 +105,7 @@
 
 import com.android.internal.R;
 import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.NotificationProgressModel;
 
 import junit.framework.Assert;
 
@@ -2414,7 +2415,7 @@
 
     @Test
     @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
-    public void progressStyle_getProgressMax_nooSegments_returnsDefault() {
+    public void progressStyle_getProgressMax_noSegments_returnsDefault() {
         final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
         progressStyle.setProgressSegments(Collections.emptyList());
         assertThat(progressStyle.getProgressMax()).isEqualTo(100);
@@ -2459,6 +2460,211 @@
 
     @Test
     @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_getProgressMax_onSegmentLimitExceeded_returnsSumOfSegmentLength() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        // limit is 10 for ProgressStyle
+        for (int i = 0; i < 30; i++) {
+            progressStyle
+                    .addProgressSegment(new Notification.ProgressStyle.Segment(10));
+        }
+
+        // THEN
+        assertThat(progressStyle.getProgressMax()).isEqualTo(300);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_addProgressSegment_dropsInvalidSegments() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        // Segments should be a positive integer.
+        progressStyle
+                .addProgressSegment(new Notification.ProgressStyle.Segment(0));
+        progressStyle
+                .addProgressSegment(new Notification.ProgressStyle.Segment(-1));
+
+        // THEN
+        assertThat(progressStyle.getProgressSegments()).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_setProgressSegment_dropsInvalidSegments() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        // Segments should be a positive integer.
+        progressStyle
+                .setProgressSegments(List.of(new Notification.ProgressStyle.Segment(0),
+                        new Notification.ProgressStyle.Segment(-1)));
+
+        // THEN
+        assertThat(progressStyle.getProgressSegments()).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_addProgressPoint_dropsNegativePoints() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        // Points should not be a negative integer.
+        progressStyle
+                .addProgressPoint(new Notification.ProgressStyle.Point(-1))
+                .addProgressPoint(new Notification.ProgressStyle.Point(-100));
+
+        // THEN
+        assertThat(progressStyle.getProgressPoints()).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_setProgressPoint_dropsNegativePoints() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        // Points should not be a negative integer.
+        progressStyle
+                .setProgressPoints(List.of(new Notification.ProgressStyle.Point(-1),
+                        new Notification.ProgressStyle.Point(-100)));
+
+        // THEN
+        assertThat(progressStyle.getProgressPoints()).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_createProgressModel_ignoresPointsExceedingMax() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100));
+        // Points should not larger than progress maximum.
+        progressStyle
+                .addProgressPoint(new Notification.ProgressStyle.Point(101))
+                .addProgressPoint(new Notification.ProgressStyle.Point(500));
+
+        // THEN
+        assertThat(progressStyle.createProgressModel(Color.BLUE, Color.RED).getPoints()).isEmpty();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_createProgressModel_ignoresOverLimitPoints() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100));
+
+        // maximum 4 points are going to be rendered.
+        progressStyle
+                .addProgressPoint(new Notification.ProgressStyle.Point(0))
+                .addProgressPoint(new Notification.ProgressStyle.Point(20))
+                .addProgressPoint(new Notification.ProgressStyle.Point(150))
+                .addProgressPoint(new Notification.ProgressStyle.Point(50))
+                .addProgressPoint(new Notification.ProgressStyle.Point(70))
+                .addProgressPoint(new Notification.ProgressStyle.Point(80))
+                .addProgressPoint(new Notification.ProgressStyle.Point(90))
+                .addProgressPoint(new Notification.ProgressStyle.Point(95))
+                .addProgressPoint(new Notification.ProgressStyle.Point(100));
+        final int backgroundColor = Color.RED;
+        final int defaultProgressColor = Color.BLUE;
+        final int expectedProgressColor = Notification.ProgressStyle.sanitizeProgressColor(
+                /* color = */Notification.COLOR_DEFAULT,
+                /* bg = */backgroundColor,
+                /* defaultColor = */defaultProgressColor);
+
+        // THEN
+        assertThat(progressStyle.createProgressModel(defaultProgressColor, backgroundColor)
+                .getPoints()).isEqualTo(
+                        List.of(new Notification.ProgressStyle.Point(0)
+                                .setColor(expectedProgressColor),
+                                new Notification.ProgressStyle.Point(20)
+                                .setColor(expectedProgressColor),
+                                new Notification.ProgressStyle.Point(50)
+                                .setColor(expectedProgressColor),
+                                new Notification.ProgressStyle.Point(70)
+                                .setColor(expectedProgressColor)
+                        )
+        );
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_createProgressModel_mergeSegmentsOnOverflow() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+
+        for (int i = 0; i < 15; i++) {
+            progressStyle
+                    .addProgressSegment(new Notification.ProgressStyle.Segment(10));
+        }
+
+        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
+                Color.BLUE, Color.RED);
+
+        // THEN
+        assertThat(progressModel.getSegments().size()).isEqualTo(1);
+        assertThat(progressModel.getProgressMax()).isEqualTo(150);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_createProgressModel_useSegmentColorWhenAllMatch() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        final int segmentColor = Color.YELLOW;
+        final int defaultProgressColor = Color.BLUE;
+        final int backgroundColor = Color.RED;
+        // contrast ensured color for segmentColor.
+        final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor(
+                /* color = */   segmentColor,
+                /* bg = */  backgroundColor,
+                /* defaultColor = */ defaultProgressColor);
+
+        for (int i = 0; i < 15; i++) {
+            progressStyle
+                    .addProgressSegment(new Notification.ProgressStyle.Segment(10)
+                            .setColor(segmentColor));
+        }
+
+        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
+                defaultProgressColor, backgroundColor);
+
+        // THEN
+        assertThat(progressModel.getSegments())
+                .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150)
+                        .setColor(expectedSegmentColor)));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
+    public void progressStyle_createProgressModel_useDefaultColorWhenAllNotMatch() {
+        // GIVEN
+        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
+        final int defaultProgressColor = Color.BLUE;
+        final int backgroundColor = Color.RED;
+        // contrast ensured color for default progress color.
+        final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor(
+                /* color = */  defaultProgressColor,
+                /* bg = */ backgroundColor,
+                /* defaultColor = */ defaultProgressColor);
+
+        for (int i = 0; i < 15; i++) {
+            progressStyle
+                    .addProgressSegment(new Notification.ProgressStyle.Segment(5)
+                            .setColor(Color.BLUE))
+                    .addProgressSegment(new Notification.ProgressStyle.Segment(5)
+                            .setColor(Color.CYAN));
+        }
+
+        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
+                defaultProgressColor, backgroundColor);
+
+        // THEN
+        assertThat(progressModel.getSegments())
+                .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150)
+                        .setColor(expectedSegmentColor)));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
     public void progressStyle_indeterminate_defaultValueFalse() {
         final Notification.ProgressStyle progressStyle1 = new Notification.ProgressStyle();
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index 911b7ce..10a85bc 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -120,7 +120,8 @@
         doReturn(newDisplayInfo).when(mIDisplayManager).getDisplayInfo(123);
 
         mDisplayManager.registerDisplayListener(mListener, mHandler,
-                DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
+                DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                        | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                 null /* packageName */);
 
         mController.onDisplayChanged(123);
diff --git a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
index 564460e..84bdbe0 100644
--- a/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapFactoryTest.java
@@ -16,19 +16,27 @@
 
 package android.graphics;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import android.os.ParcelFileDescriptor;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
 
-public class BitmapFactoryTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public class BitmapFactoryTest {
 
     // tests that we can decode bitmaps from MemoryFiles
     @SmallTest
+    @Test
     public void testBitmapParcelFileDescriptor() throws Exception {
         Bitmap bitmap1 = Bitmap.createBitmap(
                 new int[] { Color.BLUE }, 1, 1, Bitmap.Config.RGB_565);
diff --git a/core/tests/coretests/src/android/graphics/BitmapTest.java b/core/tests/coretests/src/android/graphics/BitmapTest.java
index 2280cf1..0126d36 100644
--- a/core/tests/coretests/src/android/graphics/BitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/BitmapTest.java
@@ -16,19 +16,28 @@
 
 package android.graphics;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.hardware.HardwareBuffer;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
 
-public class BitmapTest extends TestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BitmapTest {
 
-    @SmallTest
+    @Test
     public void testBasic() throws Exception {
         Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
         Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
@@ -63,7 +72,7 @@
         assertTrue("getConfig", bm3.getConfig() == Bitmap.Config.ARGB_8888);
     }
 
-    @SmallTest
+    @Test
     public void testMutability() throws Exception {
         Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
         Bitmap bm2 = Bitmap.createBitmap(new int[100 * 200], 100, 200,
@@ -82,7 +91,7 @@
         }
     }
 
-    @SmallTest
+    @Test
     public void testGetPixelsWithAlpha() throws Exception {
         int[] colors = new int[100];
         for (int i = 0; i < 100; i++) {
@@ -108,7 +117,7 @@
 
     }
 
-    @SmallTest
+    @Test
     public void testGetPixelsWithoutAlpha() throws Exception {
         int[] colors = new int[100];
         for (int i = 0; i < 100; i++) {
@@ -125,7 +134,7 @@
         }
     }
 
-    @SmallTest
+    @Test
     public void testSetPixelsWithAlpha() throws Exception {
         int[] colors = new int[100];
         for (int i = 0; i < 100; i++) {
@@ -151,7 +160,7 @@
         }
     }
 
-    @SmallTest
+    @Test
     public void testSetPixelsWithoutAlpha() throws Exception {
         int[] colors = new int[100];
         for (int i = 0; i < 100; i++) {
@@ -181,7 +190,7 @@
         return unpre;
     }
 
-    @SmallTest
+    @Test
     public void testSetPixelsWithNonOpaqueAlpha() throws Exception {
         int[] colors = new int[256];
         for (int i = 0; i < 256; i++) {
@@ -238,10 +247,13 @@
         }
     }
 
-    @SmallTest
+    private static final int GRAPHICS_USAGE =
+            GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_SW_READ_OFTEN
+                    | GraphicBuffer.USAGE_SW_WRITE_OFTEN;
+
+    @Test
     public void testWrapHardwareBufferWithSrgbColorSpace() {
-        GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888,
-                GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_SOFTWARE_MASK);
+        GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888, GRAPHICS_USAGE);
         Canvas canvas = buffer.lockCanvas();
         canvas.drawColor(Color.YELLOW);
         buffer.unlockCanvasAndPost(canvas);
@@ -252,10 +264,9 @@
         assertEquals(ColorSpace.get(ColorSpace.Named.SRGB), hardwareBitmap.getColorSpace());
     }
 
-    @SmallTest
+    @Test
     public void testWrapHardwareBufferWithDisplayP3ColorSpace() {
-        GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888,
-                GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_SOFTWARE_MASK);
+        GraphicBuffer buffer = GraphicBuffer.create(10, 10, PixelFormat.RGBA_8888, GRAPHICS_USAGE);
         Canvas canvas = buffer.lockCanvas();
         canvas.drawColor(Color.YELLOW);
         buffer.unlockCanvasAndPost(canvas);
@@ -267,7 +278,7 @@
         assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), hardwareBitmap.getColorSpace());
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithDirectByteBuffer() {
         // Initialize Bitmap
         final int width = 2;
@@ -305,7 +316,7 @@
         assertTrue(bm2.sameAs(bm1));
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithDirectShortBuffer() {
         // Initialize Bitmap
         final int width = 2;
@@ -344,7 +355,7 @@
         assertTrue(bm2.sameAs(bm1));
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithDirectIntBuffer() {
         // Initialize Bitmap
         final int width = 2;
@@ -383,7 +394,7 @@
         assertTrue(bm2.sameAs(bm1));
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithHeapByteBuffer() {
         // Initialize Bitmap
         final int width = 2;
@@ -420,7 +431,7 @@
         assertTrue(bm2.sameAs(bm1));
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithHeapShortBuffer() {
         // Initialize Bitmap
         final int width = 2;
@@ -457,7 +468,7 @@
         assertTrue(bm2.sameAs(bm1));
     }
 
-    @SmallTest
+    @Test
     public void testCopyWithHeapIntBuffer() {
         // Initialize Bitmap
         final int width = 2;
diff --git a/core/tests/coretests/src/android/graphics/ColorStateListTest.java b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
index ab41bd0..5cc915e 100644
--- a/core/tests/coretests/src/android/graphics/ColorStateListTest.java
+++ b/core/tests/coretests/src/android/graphics/ColorStateListTest.java
@@ -16,33 +16,41 @@
 
 package android.graphics;
 
+import static org.junit.Assert.assertEquals;
+
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
-import android.test.AndroidTestCase;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.frameworks.coretests.R;
 
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 /**
- * Tests of {@link android.graphics.ColorStateList}
+ * Tests of {@link ColorStateList}
  */
 
-public class ColorStateListTest extends AndroidTestCase {
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ColorStateListTest {
 
     private Resources mResources;
     private int mFailureColor;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mResources = mContext.getResources();
+    @Before
+    public void setUp() throws Exception {
+        mResources = InstrumentationRegistry.getInstrumentation().getContext().getResources();
         mFailureColor = mResources.getColor(R.color.failColor);
     }
 
-    @SmallTest
+    @Test
     public void testStateIsInList() throws Exception {
         ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
         int[] focusedState = {android.R.attr.state_focused};
@@ -50,7 +58,7 @@
         assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
     }
 
-    @SmallTest
+    @Test
     public void testStateIsInList_proto() throws Exception {
         ColorStateList colorStateList = recreateFromProto(
                 mResources.getColorStateList(R.color.color1));
@@ -59,7 +67,7 @@
         assertEquals(mResources.getColor(R.color.testcolor1), focusColor);
     }
 
-    @SmallTest
+    @Test
     public void testEmptyState() throws Exception {
         ColorStateList colorStateList = mResources.getColorStateList(R.color.color1);
         int[] emptyState = {};
@@ -67,7 +75,7 @@
         assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
     }
 
-    @SmallTest
+    @Test
     public void testEmptyState_proto() throws Exception {
         ColorStateList colorStateList = recreateFromProto(
                 mResources.getColorStateList(R.color.color1));
@@ -76,22 +84,23 @@
         assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
     }
 
-    @SmallTest
+    @Test
     public void testGetColor() throws Exception {
         int defaultColor = mResources.getColor(R.color.color1);
         assertEquals(mResources.getColor(R.color.testcolor2), defaultColor);
     }
 
-    @SmallTest
+    @Test
     public void testGetColorWhenListHasNoDefault() throws Exception {
         int defaultColor = mResources.getColor(R.color.color_no_default);
         assertEquals(mResources.getColor(R.color.testcolor1), defaultColor);
     }
 
-    @SmallTest
+    @Test
     public void testLstar() throws Exception {
+        var cl = ColorStateList.valueOf(mResources.getColor(R.color.testcolor2)).withLStar(50.0f);
         int defaultColor = mResources.getColor(R.color.color_with_lstar);
-        assertEquals(mResources.getColor(R.color.testcolor3), defaultColor);
+        assertEquals(cl.getDefaultColor(), defaultColor);
     }
 
     private ColorStateList recreateFromProto(ColorStateList colorStateList) throws Exception {
diff --git a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
index 52cc4ca..063bdf5 100644
--- a/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
+++ b/core/tests/coretests/src/android/graphics/FontFileUtilTest.java
@@ -30,9 +30,11 @@
 import android.util.Pair;
 
 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;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -43,6 +45,7 @@
 import java.nio.channels.FileChannel;
 
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class FontFileUtilTest {
     private static final String TAG = "FontFileUtilTest";
     private static final String CACHE_FILE_PREFIX = ".font";
diff --git a/core/tests/coretests/src/android/graphics/GraphicsTests.java b/core/tests/coretests/src/android/graphics/GraphicsTests.java
deleted file mode 100644
index 70f5976..0000000
--- a/core/tests/coretests/src/android/graphics/GraphicsTests.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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.graphics;
-
-import junit.framework.TestSuite;
-
-public class GraphicsTests {
-    public static TestSuite suite() {
-        TestSuite suite = new TestSuite(GraphicsTests.class.getName());
-
-        suite.addTestSuite(BitmapTest.class);
-        return suite;
-    }
-}
diff --git a/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java
index 8a54e5b..816bde6 100644
--- a/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintFontVariationTest.java
@@ -21,10 +21,9 @@
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.test.InstrumentationTestCase;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.text.flags.Flags;
 
@@ -37,7 +36,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class PaintFontVariationTest extends InstrumentationTestCase {
+public class PaintFontVariationTest {
     @Rule
     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
diff --git a/core/tests/coretests/src/android/graphics/PaintTest.java b/core/tests/coretests/src/android/graphics/PaintTest.java
index 878ba70..56760d7 100644
--- a/core/tests/coretests/src/android/graphics/PaintTest.java
+++ b/core/tests/coretests/src/android/graphics/PaintTest.java
@@ -18,19 +18,26 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
-import android.test.InstrumentationTestCase;
 import android.text.TextUtils;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.text.flags.Flags;
 
 import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -38,13 +45,14 @@
 /**
  * PaintTest tests {@link Paint}.
  */
-public class PaintTest extends InstrumentationTestCase {
+@RunWith(AndroidJUnit4.class)
+public class PaintTest {
     @Rule
     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
 
     private static final String FONT_PATH = "fonts/HintedAdvanceWidthTest-Regular.ttf";
 
-    static void assertEquals(String message, float[] expected, float[] actual) {
+    static void assertFloatArrayEquals(String message, float[] expected, float[] actual) {
         if (expected.length != actual.length) {
             fail(message + " expected array length:<" + expected.length + "> but was:<"
                     + actual.length + ">");
@@ -88,9 +96,10 @@
     };
 
     @SmallTest
+    @Test
     public void testHintingWidth() {
         final Typeface fontTypeface = Typeface.createFromAsset(
-                getInstrumentation().getContext().getAssets(), FONT_PATH);
+                InstrumentationRegistry.getInstrumentation().getContext().getAssets(), FONT_PATH);
         Paint paint = new Paint();
         paint.setTypeface(fontTypeface);
 
@@ -103,12 +112,14 @@
 
             paint.setHinting(Paint.HINTING_OFF);
             paint.getTextWidths(String.valueOf(testCase.mText), widths);
-            assertEquals("Text width of '" + testCase.mText + "' without hinting is not expected.",
+            assertFloatArrayEquals(
+                    "Text width of '" + testCase.mText + "' without hinting is not expected.",
                     testCase.mWidthWithoutHinting, widths);
 
             paint.setHinting(Paint.HINTING_ON);
             paint.getTextWidths(String.valueOf(testCase.mText), widths);
-            assertEquals("Text width of '" + testCase.mText + "' with hinting is not expected.",
+            assertFloatArrayEquals(
+                    "Text width of '" + testCase.mText + "' with hinting is not expected.",
                     testCase.mWidthWithHinting, widths);
         }
     }
@@ -131,9 +142,11 @@
         return sb.toString();
     }
 
+    @Test
     public void testHasGlyph_variationSelectors() {
         final Typeface fontTypeface = Typeface.createFromAsset(
-                getInstrumentation().getContext().getAssets(), "fonts/hasGlyphTestFont.ttf");
+                InstrumentationRegistry.getInstrumentation().getContext().getAssets(),
+                "fonts/hasGlyphTestFont.ttf");
         Paint p = new Paint();
         p.setTypeface(fontTypeface);
 
@@ -175,6 +188,7 @@
         }
     }
 
+    @Test
     public void testGetTextRunAdvances() {
         {
             // LTR
@@ -231,6 +245,7 @@
         }
     }
 
+    @Test
     public void testGetTextRunAdvances_invalid() {
         Paint p = new Paint();
         char[] text = "test".toCharArray();
@@ -284,6 +299,7 @@
         }
     }
 
+    @Test
     public void testMeasureTextBidi() {
         Paint p = new Paint();
         {
@@ -340,18 +356,21 @@
         }
     }
 
+    @Test
     public void testSetGetWordSpacing() {
         Paint p = new Paint();
-        assertEquals(0.0f, p.getWordSpacing());  // The default value should be 0.
+        assertEquals(0.0f, p.getWordSpacing(), 0.0f);  // The default value should be 0.
         p.setWordSpacing(1.0f);
-        assertEquals(1.0f, p.getWordSpacing());
+        assertEquals(1.0f, p.getWordSpacing(), 0.0f);
         p.setWordSpacing(-2.0f);
-        assertEquals(-2.0f, p.getWordSpacing());
+        assertEquals(-2.0f, p.getWordSpacing(), 0.0f);
     }
 
+    @Test
     public void testGetUnderlinePositionAndThickness() {
         final Typeface fontTypeface = Typeface.createFromAsset(
-                getInstrumentation().getContext().getAssets(), "fonts/underlineTestFont.ttf");
+                InstrumentationRegistry.getInstrumentation().getContext().getAssets(),
+                "fonts/underlineTestFont.ttf");
         final Paint p = new Paint();
         final int textSize = 100;
         p.setTextSize(textSize);
@@ -391,6 +410,7 @@
         return ccByChars;
     }
 
+    @Test
     public void testCluster() {
         final Paint p = new Paint();
         p.setTextSize(100);
@@ -417,6 +437,7 @@
     }
 
     @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+    @Test
     public void testDerivedFromSameTypeface() {
         final Paint p = new Paint();
 
@@ -432,6 +453,7 @@
     }
 
     @RequiresFlagsEnabled(Flags.FLAG_TYPEFACE_CACHE_FOR_VAR_SETTINGS)
+    @Test
     public void testDerivedFromChained() {
         final Paint p = new Paint();
 
diff --git a/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
index e1ca7df..fbaf502 100644
--- a/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
+++ b/core/tests/coretests/src/android/graphics/ThreadBitmapTest.java
@@ -16,17 +16,17 @@
 
 package android.graphics;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 
-import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class ThreadBitmapTest extends TestCase {
-
-    @Override
-    protected void setUp() throws Exception {
-    }
+@RunWith(AndroidJUnit4.class)
+public class ThreadBitmapTest {
 
     @LargeTest
+    @Test
     public void testCreation() {
         for (int i = 0; i < 200; i++) {
 
@@ -44,4 +44,3 @@
         public void run() {}
     }
 }
-
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 1429272..2b6eda8f 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -39,6 +39,8 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.text.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -514,9 +516,14 @@
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
 
         paint.setElegantTextHeight(false);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
-        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+        if (Flags.deprecateElegantTextHeightApi()) {
+            // Calling setElegantTextHeight is no-op.
+            assertTrue(paint.isElegantTextHeight());
+        } else {
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+            assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+        }
     }
 
     @Test
@@ -553,9 +560,14 @@
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
 
         paint.setElegantTextHeight(false);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
-        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f);
+        if (Flags.deprecateElegantTextHeightApi()) {
+            // Calling setElegantTextHeight is no-op.
+            assertTrue(paint.isElegantTextHeight());
+        } else {
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+            assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f);
+        }
 
         testTypeface = fontMap.get("sans-serif");
         assertNotNull(testTypeface);
@@ -566,9 +578,14 @@
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
 
         paint.setElegantTextHeight(false);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
-        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
-        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f);
+        if (Flags.deprecateElegantTextHeightApi()) {
+            // Calling setElegantTextHeight is no-op.
+            assertTrue(paint.isElegantTextHeight());
+        } else {
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f);
+            assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+            assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f);
+        }
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
index 7a5b306..8fa5103 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
+++ b/core/tests/coretests/src/android/hardware/display/DisplayManagerGlobalTest.java
@@ -73,9 +73,13 @@
     public final CheckFlagsRule mCheckFlagsRule =
             DeviceFlagsValueProvider.createCheckFlagsRule();
 
+    private static final long DISPLAY_CHANGE_EVENTS =
+            DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE;
+
     private static final long ALL_DISPLAY_EVENTS =
             DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+            | DISPLAY_CHANGE_EVENTS
             | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
 
     @Mock
@@ -127,7 +131,7 @@
         final DisplayInfo newDisplayInfo = new DisplayInfo();
         newDisplayInfo.rotation++;
         doReturn(newDisplayInfo).when(mDisplayManager).getDisplayInfo(displayId);
-        callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+        callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
         waitForHandler();
         Mockito.verify(mDisplayListener).onDisplayChanged(eq(displayId));
         Mockito.verifyNoMoreInteractions(mDisplayListener);
@@ -186,8 +190,8 @@
 
         mDisplayManagerGlobal.registerDisplayListener(mDisplayListener, mHandler,
                 ALL_DISPLAY_EVENTS
-                        & ~DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED, null);
-        callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                        & ~DISPLAY_CHANGE_EVENTS, null);
+        callback.onDisplayEvent(displayId, DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
         waitForHandler();
         Mockito.verifyZeroInteractions(mDisplayListener);
 
@@ -257,8 +261,7 @@
                         | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
                 null /* packageName */);
         mDisplayManagerGlobal.registerDisplayListener(mDisplayListener2, mHandler,
-                DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
-                null /* packageName */);
+                DISPLAY_CHANGE_EVENTS, null /* packageName */);
 
         mDisplayManagerGlobal.handleDisplayChangeFromWindowManager(321);
         waitForHandler();
@@ -299,49 +302,48 @@
 
     @Test
     @RequiresFlagsEnabled(Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS)
-    public void testMapFlagsToInternalEventFlag() {
+    public void testMapFiltersToInternalEventFlag() {
         // Test public flags mapping
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_ADDED, 0));
-        assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED,
-                mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED, 0));
+                        .mapFiltersToInternalEventFlag(DisplayManager.EVENT_TYPE_DISPLAY_ADDED, 0));
+        assertEquals(DISPLAY_CHANGE_EVENTS, mDisplayManagerGlobal
+                .mapFiltersToInternalEventFlag(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED, 0));
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED,
-                mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED, 0));
+                mDisplayManagerGlobal.mapFiltersToInternalEventFlag(
+                        DisplayManager.EVENT_TYPE_DISPLAY_REMOVED, 0));
         assertEquals(INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(
-                                DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE,
+                        .mapFiltersToInternalEventFlag(
+                                DisplayManager.EVENT_TYPE_DISPLAY_REFRESH_RATE,
                                 0));
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_STATE,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(
-                                DisplayManager.EVENT_FLAG_DISPLAY_STATE,
+                        .mapFiltersToInternalEventFlag(
+                                DisplayManager.EVENT_TYPE_DISPLAY_STATE,
                                 0));
 
         // test private flags mapping
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(0,
-                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED));
+                        .mapFiltersToInternalEventFlag(0,
+                                DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED));
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_HDR_SDR_RATIO_CHANGED,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(0,
-                                DisplayManager.PRIVATE_EVENT_FLAG_HDR_SDR_RATIO_CHANGED));
+                        .mapFiltersToInternalEventFlag(0,
+                                DisplayManager.PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED));
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(0,
-                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                        .mapFiltersToInternalEventFlag(0,
+                                DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
 
         // Test both public and private flags mapping
         assertEquals(DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED
                         | INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE,
                 mDisplayManagerGlobal
-                        .mapFlagsToInternalEventFlag(
-                                DisplayManager.EVENT_FLAG_DISPLAY_REFRESH_RATE,
-                                DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                        .mapFiltersToInternalEventFlag(
+                                DisplayManager.EVENT_TYPE_DISPLAY_REFRESH_RATE,
+                                DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
     }
 
     private void waitForHandler() {
diff --git a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
index 4a227d8..255d09b 100644
--- a/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
+++ b/core/tests/coretests/src/android/hardware/display/DisplayTopologyTest.kt
@@ -86,7 +86,7 @@
         verifyDisplay(display1, displayId1, width1, height1, noOfChildren = 1)
 
         val display2 = display1.children[0]
-        verifyDisplay(display1.children[0], displayId2, width2, height2, POSITION_TOP,
+        verifyDisplay(display2, displayId2, width2, height2, POSITION_TOP,
             offset = width1 / 2 - width2 / 2, noOfChildren = 1)
 
         var display = display2
@@ -99,6 +99,76 @@
     }
 
     @Test
+    fun updateDisplay() {
+        val displayId = 1
+        val width = 800f
+        val height = 600f
+
+        val newWidth = 1000f
+        val newHeight = 500f
+        topology.addDisplay(displayId, width, height)
+        assertThat(topology.updateDisplay(displayId, newWidth, newHeight)).isTrue()
+
+        assertThat(topology.primaryDisplayId).isEqualTo(displayId)
+        verifyDisplay(topology.root!!, displayId, newWidth, newHeight, noOfChildren = 0)
+    }
+
+    @Test
+    fun updateDisplay_notUpdated() {
+        val displayId = 1
+        val width = 800f
+        val height = 600f
+        topology.addDisplay(displayId, width, height)
+
+        // Same size
+        assertThat(topology.updateDisplay(displayId, width, height)).isFalse()
+
+        // Display doesn't exist
+        assertThat(topology.updateDisplay(/* displayId= */ 100, width, height)).isFalse()
+
+        assertThat(topology.primaryDisplayId).isEqualTo(displayId)
+        verifyDisplay(topology.root!!, displayId, width, height, noOfChildren = 0)
+    }
+
+    @Test
+    fun updateDisplayDoesNotAffectDefaultTopology() {
+        val width1 = 700f
+        val height = 600f
+        topology.addDisplay(/* displayId= */ 1, width1, height)
+
+        val width2 = 800f
+        val noOfDisplays = 30
+        for (i in 2..noOfDisplays) {
+            topology.addDisplay(/* displayId= */ i, width2, height)
+        }
+
+        val displaysToUpdate = arrayOf(3, 7, 18)
+        val newWidth = 1000f
+        val newHeight = 1500f
+        for (i in displaysToUpdate) {
+            assertThat(topology.updateDisplay(/* displayId= */ i, newWidth, newHeight)).isTrue()
+        }
+
+        assertThat(topology.primaryDisplayId).isEqualTo(1)
+
+        val display1 = topology.root!!
+        verifyDisplay(display1, id = 1, width1, height, noOfChildren = 1)
+
+        val display2 = display1.children[0]
+        verifyDisplay(display2, id = 2, width2, height, POSITION_TOP,
+            offset = width1 / 2 - width2 / 2, noOfChildren = 1)
+
+        var display = display2
+        for (i in 3..noOfDisplays) {
+            display = display.children[0]
+            // The last display should have no children
+            verifyDisplay(display, id = i, if (i in displaysToUpdate) newWidth else width2,
+                if (i in displaysToUpdate) newHeight else height, POSITION_RIGHT, offset = 0f,
+                noOfChildren = if (i < noOfDisplays) 1 else 0)
+        }
+    }
+
+    @Test
     fun removeDisplays() {
         val displayId1 = 1
         val width1 = 800f
@@ -117,7 +187,7 @@
         }
 
         var removedDisplays = arrayOf(20)
-        topology.removeDisplay(20)
+        assertThat(topology.removeDisplay(20)).isTrue()
 
         assertThat(topology.primaryDisplayId).isEqualTo(displayId1)
 
@@ -139,11 +209,11 @@
                 noOfChildren = if (i < noOfDisplays) 1 else 0)
         }
 
-        topology.removeDisplay(22)
+        assertThat(topology.removeDisplay(22)).isTrue()
         removedDisplays += 22
-        topology.removeDisplay(23)
+        assertThat(topology.removeDisplay(23)).isTrue()
         removedDisplays += 23
-        topology.removeDisplay(25)
+        assertThat(topology.removeDisplay(25)).isTrue()
         removedDisplays += 25
 
         assertThat(topology.primaryDisplayId).isEqualTo(displayId1)
@@ -174,7 +244,7 @@
         val height = 600f
 
         topology.addDisplay(displayId, width, height)
-        topology.removeDisplay(displayId)
+        assertThat(topology.removeDisplay(displayId)).isTrue()
 
         assertThat(topology.primaryDisplayId).isEqualTo(Display.INVALID_DISPLAY)
         assertThat(topology.root).isNull()
@@ -187,7 +257,7 @@
         val height = 600f
 
         topology.addDisplay(displayId, width, height)
-        topology.removeDisplay(3)
+        assertThat(topology.removeDisplay(3)).isFalse()
 
         assertThat(topology.primaryDisplayId).isEqualTo(displayId)
         verifyDisplay(topology.root!!, displayId, width, height, noOfChildren = 0)
@@ -203,7 +273,7 @@
         topology = DisplayTopology(/* root= */ null, displayId2)
         topology.addDisplay(displayId1, width, height)
         topology.addDisplay(displayId2, width, height)
-        topology.removeDisplay(displayId2)
+        assertThat(topology.removeDisplay(displayId2)).isTrue()
 
         assertThat(topology.primaryDisplayId).isEqualTo(displayId1)
         verifyDisplay(topology.root!!, displayId1, width, height, noOfChildren = 0)
diff --git a/core/tests/coretests/src/android/net/http/OWNERS b/core/tests/coretests/src/android/net/http/OWNERS
new file mode 100644
index 0000000..c93a419
--- /dev/null
+++ b/core/tests/coretests/src/android/net/http/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/net/http/OWNERS
diff --git a/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
index 04aa62a..a6ad80d 100644
--- a/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
+++ b/core/tests/coretests/src/android/net/http/X509TrustManagerExtensionsTest.java
@@ -16,6 +16,17 @@
 
 package android.net.http;
 
+import static org.junit.Assert.fail;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.org.conscrypt.TrustManagerImpl;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
 import java.security.KeyStore;
 import java.security.cert.X509Certificate;
 
@@ -23,11 +34,9 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
-import junit.framework.TestCase;
-
-import com.android.org.conscrypt.TrustManagerImpl;
-
-public class X509TrustManagerExtensionsTest extends TestCase {
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class X509TrustManagerExtensionsTest {
 
     private class NotATrustManagerImpl implements X509TrustManager {
 
@@ -40,6 +49,7 @@
         }
     }
 
+    @Test
     public void testBadCast() throws Exception {
         NotATrustManagerImpl ntmi = new NotATrustManagerImpl();
         try {
@@ -49,12 +59,14 @@
         }
     }
 
+    @Test
     public void testGoodCast() throws Exception {
         String defaultType = KeyStore.getDefaultType();
         TrustManagerImpl tmi = new TrustManagerImpl(KeyStore.getInstance(defaultType));
         X509TrustManagerExtensions tme = new X509TrustManagerExtensions(tmi);
     }
 
+    @Test
     public void testNormalUseCase() throws Exception {
         String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
         TrustManagerFactory tmf = TrustManagerFactory.getInstance(defaultAlgorithm);
diff --git a/core/tests/coretests/src/android/os/PerfettoTraceTest.java b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
new file mode 100644
index 0000000..292f750
--- /dev/null
+++ b/core/tests/coretests/src/android/os/PerfettoTraceTest.java
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static android.os.PerfettoTrace.Category;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static perfetto.protos.ChromeLatencyInfoOuterClass.ChromeLatencyInfo.LatencyComponentType.COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH;
+import static perfetto.protos.ChromeLatencyInfoOuterClass.ChromeLatencyInfo.LatencyComponentType.COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL;
+
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import perfetto.protos.ChromeLatencyInfoOuterClass.ChromeLatencyInfo;
+import perfetto.protos.ChromeLatencyInfoOuterClass.ChromeLatencyInfo.ComponentInfo;
+import perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
+import perfetto.protos.DebugAnnotationOuterClass.DebugAnnotation;
+import perfetto.protos.DebugAnnotationOuterClass.DebugAnnotationName;
+import perfetto.protos.InternedDataOuterClass.InternedData;
+import perfetto.protos.SourceLocationOuterClass.SourceLocation;
+import perfetto.protos.TraceConfigOuterClass.TraceConfig;
+import perfetto.protos.TraceConfigOuterClass.TraceConfig.BufferConfig;
+import perfetto.protos.TraceConfigOuterClass.TraceConfig.DataSource;
+import perfetto.protos.TraceConfigOuterClass.TraceConfig.TriggerConfig;
+import perfetto.protos.TraceConfigOuterClass.TraceConfig.TriggerConfig.Trigger;
+import perfetto.protos.TraceOuterClass.Trace;
+import perfetto.protos.TracePacketOuterClass.TracePacket;
+import perfetto.protos.TrackDescriptorOuterClass.TrackDescriptor;
+import perfetto.protos.TrackEventConfigOuterClass.TrackEventConfig;
+import perfetto.protos.TrackEventOuterClass.EventCategory;
+import perfetto.protos.TrackEventOuterClass.EventName;
+import perfetto.protos.TrackEventOuterClass.TrackEvent;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is used to test the native tracing support. Run this test
+ * while tracing on the emulator and then run traceview to view the trace.
+ */
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = PerfettoTrace.class)
+public class PerfettoTraceTest {
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule =
+            DeviceFlagsValueProvider.createCheckFlagsRule(
+                    InstrumentationRegistry.getInstrumentation().getUiAutomation());
+
+    private static final String TAG = "PerfettoTraceTest";
+    private static final String FOO = "foo";
+    private static final String BAR = "bar";
+
+    private static final Category FOO_CATEGORY = new Category(FOO);
+
+    private final Set<String> mCategoryNames = new ArraySet<>();
+    private final Set<String> mEventNames = new ArraySet<>();
+    private final Set<String> mDebugAnnotationNames = new ArraySet<>();
+    private final Set<String> mTrackNames = new ArraySet<>();
+
+    static {
+        try {
+            System.loadLibrary("perfetto_trace_test_jni");
+            Log.i(TAG, "Successfully loaded trace_test native library");
+        } catch (UnsatisfiedLinkError ule) {
+            Log.w(TAG, "Could not load trace_test native library");
+        }
+    }
+
+    @Before
+    public void setUp() {
+        PerfettoTrace.register();
+        nativeRegisterPerfetto();
+        FOO_CATEGORY.register();
+
+        mCategoryNames.clear();
+        mEventNames.clear();
+        mDebugAnnotationNames.clear();
+        mTrackNames.clear();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testDebugAnnotations() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder()
+                .addFlow(2)
+                .addTerminatingFlow(3)
+                .addArg("long_val", 10000000000L)
+                .addArg("bool_val", true)
+                .addArg("double_val", 3.14)
+                .addArg("string_val", FOO)
+                .build();
+        PerfettoTrace.instant(FOO_CATEGORY, "event", extra);
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        boolean hasDebugAnnotations = false;
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
+                        && event.getDebugAnnotationsCount() == 4 && event.getFlowIdsCount() == 1
+                        && event.getTerminatingFlowIdsCount() == 1) {
+                    hasDebugAnnotations = true;
+
+                    List<DebugAnnotation> annotations = event.getDebugAnnotationsList();
+
+                    assertThat(annotations.get(0).getIntValue()).isEqualTo(10000000000L);
+                    assertThat(annotations.get(1).getBoolValue()).isTrue();
+                    assertThat(annotations.get(2).getDoubleValue()).isEqualTo(3.14);
+                    assertThat(annotations.get(3).getStringValue()).isEqualTo(FOO);
+                }
+            }
+
+            collectInternedData(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasDebugAnnotations).isTrue();
+        assertThat(mCategoryNames).contains(FOO);
+
+        assertThat(mDebugAnnotationNames).contains("long_val");
+        assertThat(mDebugAnnotationNames).contains("bool_val");
+        assertThat(mDebugAnnotationNames).contains("double_val");
+        assertThat(mDebugAnnotationNames).contains("string_val");
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testDebugAnnotationsWithLamda() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrace.instant(FOO_CATEGORY, "event", e -> e.addArg("long_val", 123L));
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        boolean hasDebugAnnotations = false;
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
+                        && event.getDebugAnnotationsCount() == 1) {
+                    hasDebugAnnotations = true;
+
+                    List<DebugAnnotation> annotations = event.getDebugAnnotationsList();
+                    assertThat(annotations.get(0).getIntValue()).isEqualTo(123L);
+                }
+            }
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasDebugAnnotations).isTrue();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testNamedTrack() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra beginExtra = PerfettoTrackEventExtra.builder()
+                .usingNamedTrack(FOO, PerfettoTrace.getProcessTrackUuid())
+                .build();
+        PerfettoTrace.begin(FOO_CATEGORY, "event", beginExtra);
+
+        PerfettoTrackEventExtra endExtra = PerfettoTrackEventExtra.builder()
+                .usingNamedTrack("bar", PerfettoTrace.getThreadTrackUuid(Process.myTid()))
+                .build();
+        PerfettoTrace.end(FOO_CATEGORY, endExtra);
+
+        Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
+
+        boolean hasTrackEvent = false;
+        boolean hasTrackUuid = false;
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_SLICE_BEGIN.equals(event.getType())
+                        && event.hasTrackUuid()) {
+                    hasTrackUuid = true;
+                }
+
+                if (TrackEvent.Type.TYPE_SLICE_END.equals(event.getType())
+                        && event.hasTrackUuid()) {
+                    hasTrackUuid &= true;
+                }
+            }
+
+            collectInternedData(packet);
+            collectTrackNames(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasTrackUuid).isTrue();
+        assertThat(mCategoryNames).contains(FOO);
+        assertThat(mTrackNames).contains(FOO);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testCounter() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra intExtra = PerfettoTrackEventExtra.builder()
+                .usingCounterTrack(FOO, PerfettoTrace.getProcessTrackUuid())
+                .setCounter(16)
+                .build();
+        PerfettoTrace.counter(FOO_CATEGORY, intExtra);
+
+        PerfettoTrackEventExtra doubleExtra = PerfettoTrackEventExtra.builder()
+                .usingCounterTrack("bar", PerfettoTrace.getProcessTrackUuid())
+                .setCounter(3.14)
+                .build();
+        PerfettoTrace.counter(FOO_CATEGORY, doubleExtra);
+
+        Trace trace = Trace.parseFrom(nativeStopTracing(ptr));
+
+        boolean hasTrackEvent = false;
+        boolean hasCounterValue = false;
+        boolean hasDoubleCounterValue = false;
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+                        && event.getCounterValue() == 16) {
+                    hasCounterValue = true;
+                }
+
+                if (TrackEvent.Type.TYPE_COUNTER.equals(event.getType())
+                        && event.getDoubleCounterValue() == 3.14) {
+                    hasDoubleCounterValue = true;
+                }
+            }
+
+            collectTrackNames(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasCounterValue).isTrue();
+        assertThat(hasDoubleCounterValue).isTrue();
+        assertThat(mTrackNames).contains(FOO);
+        assertThat(mTrackNames).contains(BAR);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testProto() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra extra5 = PerfettoTrackEventExtra.builder()
+                .beginProto()
+                .beginNested(33L)
+                .addField(4L, 2L)
+                .addField(3, "ActivityManagerService.java:11489")
+                .endNested()
+                .addField(2001, "AIDL::IActivityManager")
+                .endProto()
+                .build();
+        PerfettoTrace.instant(FOO_CATEGORY, "event_proto", extra5);
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        boolean hasSourceLocation = false;
+
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
+                        && event.hasSourceLocation()) {
+                    SourceLocation loc = event.getSourceLocation();
+                    if ("ActivityManagerService.java:11489".equals(loc.getFunctionName())
+                            && loc.getLineNumber() == 2) {
+                        hasSourceLocation = true;
+                    }
+                }
+            }
+
+            collectInternedData(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasSourceLocation).isTrue();
+        assertThat(mCategoryNames).contains(FOO);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testProtoNested() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra extra6 = PerfettoTrackEventExtra.builder()
+                .beginProto()
+                .beginNested(29L)
+                .beginNested(4L)
+                .addField(1L, 2)
+                .addField(2L, 20000)
+                .endNested()
+                .beginNested(4L)
+                .addField(1L, 1)
+                .addField(2L, 40000)
+                .endNested()
+                .endNested()
+                .endProto()
+                .build();
+        PerfettoTrace.instant(FOO_CATEGORY, "event_proto_nested", extra6);
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        boolean hasChromeLatencyInfo = false;
+
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+
+                if (TrackEvent.Type.TYPE_INSTANT.equals(event.getType())
+                        && event.hasChromeLatencyInfo()) {
+                    ChromeLatencyInfo latencyInfo = event.getChromeLatencyInfo();
+                    if (latencyInfo.getComponentInfoCount() == 2) {
+                        hasChromeLatencyInfo = true;
+                        ComponentInfo cmpInfo1 = latencyInfo.getComponentInfo(0);
+                        assertThat(cmpInfo1.getComponentType())
+                                .isEqualTo(COMPONENT_INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL);
+                        assertThat(cmpInfo1.getTimeUs()).isEqualTo(20000);
+
+                        ComponentInfo cmpInfo2 = latencyInfo.getComponentInfo(1);
+                        assertThat(cmpInfo2.getComponentType())
+                                .isEqualTo(COMPONENT_INPUT_EVENT_LATENCY_BEGIN_RWH);
+                        assertThat(cmpInfo2.getTimeUs()).isEqualTo(40000);
+                    }
+                }
+            }
+
+            collectInternedData(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(hasChromeLatencyInfo).isTrue();
+        assertThat(mCategoryNames).contains(FOO);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testActivateTrigger() throws Exception {
+        TraceConfig traceConfig = getTriggerTraceConfig(FOO, FOO);
+
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra extra = PerfettoTrackEventExtra.builder().build();
+        PerfettoTrace.instant(FOO_CATEGORY, "event_trigger", extra);
+
+        PerfettoTrace.activateTrigger(FOO, 1000);
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        boolean hasChromeLatencyInfo = false;
+
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+            }
+
+            collectInternedData(packet);
+        }
+
+        assertThat(mCategoryNames).contains(FOO);
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testMultipleExtras() throws Exception {
+        boolean hasException = false;
+        try {
+            PerfettoTrackEventExtra.builder();
+
+            // Unclosed extra will throw an exception here
+            PerfettoTrackEventExtra.builder();
+        } catch (Exception e) {
+            hasException = true;
+        }
+
+        try {
+            PerfettoTrackEventExtra.builder().build();
+
+            // Closed extra but unused (reset hasn't been called internally) will throw an exception
+            // here.
+            PerfettoTrackEventExtra.builder();
+        } catch (Exception e) {
+            hasException &= true;
+        }
+
+        assertThat(hasException).isTrue();
+    }
+
+    @Test
+    @RequiresFlagsEnabled(android.os.Flags.FLAG_PERFETTO_SDK_TRACING_V2)
+    public void testRegister() throws Exception {
+        TraceConfig traceConfig = getTraceConfig(BAR);
+
+        Category barCategory = new Category(BAR);
+        long ptr = nativeStartTracing(traceConfig.toByteArray());
+
+        PerfettoTrackEventExtra beforeExtra = PerfettoTrackEventExtra.builder()
+                .addArg("before", 1)
+                .build();
+        PerfettoTrace.instant(barCategory, "event", beforeExtra);
+
+        barCategory.register();
+
+        PerfettoTrackEventExtra afterExtra = PerfettoTrackEventExtra.builder()
+                .addArg("after", 1)
+                .build();
+        PerfettoTrace.instant(barCategory, "event", afterExtra);
+
+        byte[] traceBytes = nativeStopTracing(ptr);
+
+        Trace trace = Trace.parseFrom(traceBytes);
+
+        boolean hasTrackEvent = false;
+        for (TracePacket packet: trace.getPacketList()) {
+            TrackEvent event;
+            if (packet.hasTrackEvent()) {
+                hasTrackEvent = true;
+                event = packet.getTrackEvent();
+            }
+
+            collectInternedData(packet);
+        }
+
+        assertThat(hasTrackEvent).isTrue();
+        assertThat(mCategoryNames).contains(BAR);
+
+        assertThat(mDebugAnnotationNames).contains("after");
+        assertThat(mDebugAnnotationNames).doesNotContain("before");
+    }
+
+    private static native long nativeStartTracing(byte[] config);
+    private static native void nativeRegisterPerfetto();
+    private static native byte[] nativeStopTracing(long ptr);
+
+    private TrackEvent getTrackEvent(Trace trace, int idx) {
+        int curIdx = 0;
+        for (TracePacket packet: trace.getPacketList()) {
+            if (packet.hasTrackEvent()) {
+                if (curIdx++ == idx) {
+                    return packet.getTrackEvent();
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private TraceConfig getTraceConfig(String cat) {
+        BufferConfig bufferConfig = BufferConfig.newBuilder().setSizeKb(1024).build();
+        TrackEventConfig trackEventConfig = TrackEventConfig
+                .newBuilder()
+                .addEnabledCategories(cat)
+                .build();
+        DataSourceConfig dsConfig = DataSourceConfig
+                .newBuilder()
+                .setName("track_event")
+                .setTargetBuffer(0)
+                .setTrackEventConfig(trackEventConfig)
+                .build();
+        DataSource ds = DataSource.newBuilder().setConfig(dsConfig).build();
+        TraceConfig traceConfig = TraceConfig
+                .newBuilder()
+                .addBuffers(bufferConfig)
+                .addDataSources(ds)
+                .build();
+        return traceConfig;
+    }
+
+    private TraceConfig getTriggerTraceConfig(String cat, String triggerName) {
+        BufferConfig bufferConfig = BufferConfig.newBuilder().setSizeKb(1024).build();
+        TrackEventConfig trackEventConfig = TrackEventConfig
+                .newBuilder()
+                .addEnabledCategories(cat)
+                .build();
+        DataSourceConfig dsConfig = DataSourceConfig
+                .newBuilder()
+                .setName("track_event")
+                .setTargetBuffer(0)
+                .setTrackEventConfig(trackEventConfig)
+                .build();
+        DataSource ds = DataSource.newBuilder().setConfig(dsConfig).build();
+        Trigger trigger = Trigger.newBuilder().setName(triggerName).build();
+        TriggerConfig triggerConfig = TriggerConfig
+                .newBuilder()
+                .setTriggerMode(TriggerConfig.TriggerMode.STOP_TRACING)
+                .setTriggerTimeoutMs(1000)
+                .addTriggers(trigger)
+                .build();
+        TraceConfig traceConfig = TraceConfig
+                .newBuilder()
+                .addBuffers(bufferConfig)
+                .addDataSources(ds)
+                .setTriggerConfig(triggerConfig)
+                .build();
+        return traceConfig;
+    }
+
+    private void collectInternedData(TracePacket packet) {
+        if (!packet.hasInternedData()) {
+            return;
+        }
+
+        InternedData data = packet.getInternedData();
+
+        for (EventCategory cat : data.getEventCategoriesList()) {
+            mCategoryNames.add(cat.getName());
+        }
+        for (EventName ev : data.getEventNamesList()) {
+            mEventNames.add(ev.getName());
+        }
+        for (DebugAnnotationName dbg : data.getDebugAnnotationNamesList()) {
+            mDebugAnnotationNames.add(dbg.getName());
+        }
+    }
+
+    private void collectTrackNames(TracePacket packet) {
+        if (!packet.hasTrackDescriptor()) {
+            return;
+        }
+        TrackDescriptor desc = packet.getTrackDescriptor();
+        mTrackNames.add(desc.getName());
+    }
+}
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index 310baa3..ea39db7 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -18,6 +18,7 @@
 package android.os;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.platform.test.annotations.IgnoreUnderRavenwood;
@@ -26,6 +27,8 @@
 import org.junit.Rule;
 import org.junit.Test;
 
+import java.util.Arrays;
+
 @IgnoreUnderRavenwood(blockedBy = Process.class)
 public class ProcessTest {
     @Rule
@@ -92,4 +95,19 @@
         assertTrue(Process.getAdvertisedMem() > 0);
         assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
     }
+
+    @Test
+    public void testGetSchedAffinity() {
+        long[] tidMasks = Process.getSchedAffinity(Process.myTid());
+        long[] pidMasks = Process.getSchedAffinity(Process.myPid());
+        checkAffinityMasks(tidMasks);
+        checkAffinityMasks(pidMasks);
+    }
+
+    static void checkAffinityMasks(long[] masks) {
+        assertNotNull(masks);
+        assertTrue(masks.length > 0);
+        assertTrue("At least one of the affinity mask should be non-zero but got "
+                + Arrays.toString(masks), Arrays.stream(masks).anyMatch(value -> value > 0));
+    }
 }
diff --git a/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java b/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java
new file mode 100644
index 0000000..45864b0
--- /dev/null
+++ b/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.advancedprotection;
+
+import static android.security.advancedprotection.AdvancedProtectionManager.ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG;
+import static android.security.advancedprotection.AdvancedProtectionManager.EXTRA_SUPPORT_DIALOG_FEATURE;
+import static android.security.advancedprotection.AdvancedProtectionManager.EXTRA_SUPPORT_DIALOG_TYPE;
+import static android.security.advancedprotection.AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G;
+import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION;
+import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_DISABLED_SETTING;
+import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_UNKNOWN;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import android.content.Intent;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AdvancedProtectionManagerTest {
+    private static final int FEATURE_ID_INVALID = -1;
+    private static final int SUPPORT_DIALOG_TYPE_INVALID = -1;
+
+    @Test
+    public void testCreateSupportIntent_validFeature_validTypeUnknown_createsIntent() {
+        Intent intent = AdvancedProtectionManager.createSupportIntent(
+                FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_UNKNOWN);
+
+        assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction());
+        assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra(
+                EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID));
+        assertEquals(SUPPORT_DIALOG_TYPE_UNKNOWN, intent.getIntExtra(EXTRA_SUPPORT_DIALOG_TYPE,
+                SUPPORT_DIALOG_TYPE_INVALID));
+    }
+
+    @Test
+    public void testCreateSupportIntent_validFeature_validTypeBlockedInteraction_createsIntent() {
+        Intent intent = AdvancedProtectionManager.createSupportIntent(
+                FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION);
+
+        assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction());
+        assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra(
+                EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID));
+        assertEquals(SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION, intent.getIntExtra(
+                EXTRA_SUPPORT_DIALOG_TYPE, SUPPORT_DIALOG_TYPE_INVALID));
+    }
+
+    @Test
+    public void testCreateSupportIntent_validFeature_validTypeDisabledSetting_createsIntent() {
+        Intent intent = AdvancedProtectionManager.createSupportIntent(
+                FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_DISABLED_SETTING);
+
+        assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction());
+        assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra(
+                EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID));
+        assertEquals(SUPPORT_DIALOG_TYPE_DISABLED_SETTING, intent.getIntExtra(
+                EXTRA_SUPPORT_DIALOG_TYPE, SUPPORT_DIALOG_TYPE_INVALID));
+    }
+
+    @Test
+    public void testCreateSupportIntent_validFeature_invalidType_throwsIllegalArgument() {
+        assertThrows(IllegalArgumentException.class, () ->
+                AdvancedProtectionManager.createSupportIntent(FEATURE_ID_DISALLOW_CELLULAR_2G,
+                        SUPPORT_DIALOG_TYPE_INVALID));
+    }
+
+    @Test
+    public void testCreateSupportIntent_invalidFeature_validType_throwsIllegalArgument() {
+        assertThrows(IllegalArgumentException.class, () ->
+                AdvancedProtectionManager.createSupportIntent(FEATURE_ID_INVALID,
+                        SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION));
+    }
+
+    @Test
+    public void testCreateSupportIntent_invalidFeature_invalidType_throwsIllegalArgument() {
+        assertThrows(IllegalArgumentException.class, () ->
+                AdvancedProtectionManager.createSupportIntent(FEATURE_ID_INVALID,
+                        SUPPORT_DIALOG_TYPE_INVALID));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index fb1efa8..8b4f714 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -1171,6 +1171,88 @@
         waitForAfterDraw();
     }
 
+    @Test
+    public void ignoreHeuristicWhenFling() throws Throwable {
+        if (!ViewProperties.vrr_enabled().orElse(true)) {
+            return;
+        }
+
+        waitForFrameRateCategoryToSettle();
+        FrameLayout host = new FrameLayout(mActivity);
+        View childView = new View(mActivity);
+        float velocity = 1000;
+
+        TranslateAnimation translateAnimation = new TranslateAnimation(
+                Animation.RELATIVE_TO_PARENT, 0f, // fromXDelta
+                Animation.RELATIVE_TO_PARENT, 0f, // toXDelta
+                Animation.RELATIVE_TO_PARENT, 1f, // fromYDelta (100%p)
+                Animation.RELATIVE_TO_PARENT, 0f  // toYDelta
+        );
+        translateAnimation.setDuration(100);
+
+        mActivityRule.runOnUiThread(() -> {
+            ViewGroup.LayoutParams fullSize = new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+            mActivity.setContentView(host, fullSize);
+            host.setFrameContentVelocity(velocity);
+            ViewGroupOverlay overlay = host.getOverlay();
+            overlay.add(childView);
+            assertEquals(velocity, host.getFrameContentVelocity());
+            assertEquals(host.getFrameContentVelocity(),
+                    ((View) childView.getParent()).getFrameContentVelocity());
+
+            mMovingView.startAnimation(translateAnimation);
+
+            // The frame rate should be "Normal" during fling gestures,
+            // even if there's a moving View.
+            assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRoot.getLastPreferredFrameRateCategory());
+        });
+        waitForAfterDraw();
+    }
+
+    @Test
+    public void ignoreHeuristicWhenFlingMovementFirst() throws Throwable {
+        if (!ViewProperties.vrr_enabled().orElse(true)) {
+            return;
+        }
+
+        waitForFrameRateCategoryToSettle();
+        FrameLayout host = new FrameLayout(mActivity);
+        View childView = new View(mActivity);
+        float velocity = 1000;
+
+        TranslateAnimation translateAnimation = new TranslateAnimation(
+                Animation.RELATIVE_TO_PARENT, 0f, // fromXDelta
+                Animation.RELATIVE_TO_PARENT, 0f, // toXDelta
+                Animation.RELATIVE_TO_PARENT, 1f, // fromYDelta (100%p)
+                Animation.RELATIVE_TO_PARENT, 0f  // toYDelta
+        );
+        translateAnimation.setDuration(100);
+
+        mActivityRule.runOnUiThread(() -> {
+            mMovingView.startAnimation(translateAnimation);
+
+            ViewGroup.LayoutParams fullSize = new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT);
+            mActivity.setContentView(host, fullSize);
+            host.setFrameContentVelocity(velocity);
+            ViewGroupOverlay overlay = host.getOverlay();
+            overlay.add(childView);
+            assertEquals(velocity, host.getFrameContentVelocity());
+            assertEquals(host.getFrameContentVelocity(),
+                    ((View) childView.getParent()).getFrameContentVelocity());
+
+            // The frame rate should be "Normal" during fling gestures,
+            // even if there's a moving View.
+            assertEquals(FRAME_RATE_CATEGORY_NORMAL,
+                    mViewRoot.getLastPreferredFrameRateCategory());
+        });
+        waitForAfterDraw();
+    }
+
     private void runAfterDraw(@NonNull Runnable runnable) {
         Handler handler = new Handler(Looper.getMainLooper());
         mAfterDrawLatch = new CountDownLatch(1);
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index ed9fc1c..18ab52d 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -25,7 +25,7 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
-import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
+import static android.view.Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST;
 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
@@ -861,10 +861,10 @@
             assertEquals(mViewRootImpl.getFrameRateCompatibility(),
                     FRAME_RATE_COMPATIBILITY_FIXED_SOURCE);
             assertFalse(mViewRootImpl.isFrameRateConflicted());
-            mViewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_GTE);
+            mViewRootImpl.votePreferredFrameRate(24, FRAME_RATE_COMPATIBILITY_AT_LEAST);
             if (toolkitFrameRateVelocityMappingReadOnly()) {
                 assertEquals(24, mViewRootImpl.getPreferredFrameRate(), 0.1);
-                assertEquals(FRAME_RATE_COMPATIBILITY_GTE,
+                assertEquals(FRAME_RATE_COMPATIBILITY_AT_LEAST,
                         mViewRootImpl.getFrameRateCompatibility());
                 assertFalse(mViewRootImpl.isFrameRateConflicted());
             } else {
@@ -888,10 +888,10 @@
 
         sInstrumentation.runOnMainSync(() -> {
             assertFalse(mViewRootImpl.isFrameRateConflicted());
-            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
+            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_AT_LEAST);
             if (toolkitFrameRateVelocityMappingReadOnly()) {
                 assertEquals(60, mViewRootImpl.getPreferredFrameRate(), 0.1);
-                assertEquals(FRAME_RATE_COMPATIBILITY_GTE,
+                assertEquals(FRAME_RATE_COMPATIBILITY_AT_LEAST,
                         mViewRootImpl.getFrameRateCompatibility());
             } else {
                 assertEquals(FRAME_RATE_CATEGORY_HIGH,
@@ -904,7 +904,7 @@
                     mViewRootImpl.getFrameRateCompatibility());
             // Should be false since 60 is a divisor of 120.
             assertFalse(mViewRootImpl.isFrameRateConflicted());
-            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_GTE);
+            mViewRootImpl.votePreferredFrameRate(60, FRAME_RATE_COMPATIBILITY_AT_LEAST);
             assertEquals(120, mViewRootImpl.getPreferredFrameRate(), 0.1);
             // compatibility should be remained the same (FRAME_RATE_COMPATIBILITY_FIXED_SOURCE)
             // since the frame rate 60 is smaller than 120.
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
index 5a4561d..f87b699 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java
@@ -266,6 +266,11 @@
         }
 
         @Override
+        void internalNotifySessionFlushEvent(int sessionId) {
+            throw new UnsupportedOperationException("should not have been called");
+        }
+
+        @Override
         void internalNotifyChildSessionStarted(int parentSessionId, int childSessionId,
                 @NonNull ContentCaptureContext clientContext) {
             throw new UnsupportedOperationException("should not have been called");
diff --git a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
index fdc00ba..610758d 100644
--- a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
+++ b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
@@ -16,8 +16,6 @@
 
 package android.window;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
 
 import static org.junit.Assert.assertEquals;
@@ -30,15 +28,9 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager.TaskDescription;
-import android.content.ComponentName;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.ColorSpace;
-import android.graphics.Point;
 import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
-import android.view.Surface;
-import android.view.SurfaceControl;
 import android.view.WindowInsets;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -54,7 +46,7 @@
 @RunWith(AndroidJUnit4.class)
 public class SnapshotDrawerUtilsTest {
 
-    private SnapshotDrawerUtils.SnapshotSurface mSnapshotSurface;
+    private SnapshotDrawerUtils.SystemBarBackgroundPainter mSystemBarBackgroundPainter;
 
     private void setupSurface(int width, int height) {
         setupSurface(width, height, new Rect(), FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
@@ -70,31 +62,14 @@
         // taskBounds
         assertEquals(width, taskBounds.width());
         assertEquals(height, taskBounds.height());
-        Point taskSize = new Point(taskBounds.width(), taskBounds.height());
 
-        final TaskSnapshot snapshot = createTaskSnapshot(width, height, taskSize, contentInsets);
         TaskDescription taskDescription = createTaskDescription(Color.WHITE,
                 Color.RED, Color.BLUE);
 
-        mSnapshotSurface = new SnapshotDrawerUtils.SnapshotSurface(
-                new SurfaceControl(), snapshot, "Test");
-        mSnapshotSurface.initiateSystemBarPainter(windowFlags, 0, 0,
-                taskDescription, WindowInsets.Type.defaultVisible());
-    }
-
-    private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
-            Rect contentInsets) {
-        final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
-                1, HardwareBuffer.USAGE_CPU_READ_RARELY);
-        return new TaskSnapshot(
-                System.currentTimeMillis(),
-                0 /* captureTime */,
-                new ComponentName("", ""), buffer,
-                ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
-                Surface.ROTATION_0, taskSize, contentInsets, new Rect() /* letterboxInsets */,
-                false, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
-                0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */,
-                0 /* uiMode */);
+        mSystemBarBackgroundPainter = new SnapshotDrawerUtils.SystemBarBackgroundPainter(
+                windowFlags, 0 /* windowPrivateFlags */, 0 /* appearance */,
+                taskDescription, 1f /* scale */, WindowInsets.Type.defaultVisible());
+        mSystemBarBackgroundPainter.setInsets(contentInsets);
     }
 
     private static TaskDescription createTaskDescription(int background,
@@ -107,134 +82,14 @@
     }
 
     @Test
-    public void fillEmptyBackground_fillHorizontally() {
-        setupSurface(200, 100);
-        final Canvas mockCanvas = mock(Canvas.class);
-        when(mockCanvas.getWidth()).thenReturn(200);
-        when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
-        verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
-    }
-
-    @Test
-    public void fillEmptyBackground_fillVertically() {
-        setupSurface(100, 200);
-        final Canvas mockCanvas = mock(Canvas.class);
-        when(mockCanvas.getWidth()).thenReturn(100);
-        when(mockCanvas.getHeight()).thenReturn(200);
-        mSnapshotSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
-        verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
-    }
-
-    @Test
-    public void fillEmptyBackground_fillBoth() {
-        setupSurface(200, 200);
-        final Canvas mockCanvas = mock(Canvas.class);
-        when(mockCanvas.getWidth()).thenReturn(200);
-        when(mockCanvas.getHeight()).thenReturn(200);
-        mSnapshotSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
-        verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
-        verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
-    }
-
-    @Test
-    public void fillEmptyBackground_dontFill_sameSize() {
-        setupSurface(100, 100);
-        final Canvas mockCanvas = mock(Canvas.class);
-        when(mockCanvas.getWidth()).thenReturn(100);
-        when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
-        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
-    }
-
-    @Test
-    public void fillEmptyBackground_dontFill_bitmapLarger() {
-        setupSurface(100, 100);
-        final Canvas mockCanvas = mock(Canvas.class);
-        when(mockCanvas.getWidth()).thenReturn(100);
-        when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
-        verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
-    }
-
-    @Test
-    public void testCalculateSnapshotCrop() {
-        final Rect contentInsets = new Rect(0, 10, 0, 10);
-        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(0, 0, 100, 90),
-                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
-    }
-
-    @Test
-    public void testCalculateSnapshotCrop_taskNotOnTop() {
-        final Rect contentInsets = new Rect(0, 10, 0, 10);
-        final Rect bounds = new Rect(0, 50, 100, 150);
-        setupSurface(100, 100, contentInsets, 0, bounds);
-        mSnapshotSurface.setFrames(bounds, contentInsets);
-        assertEquals(new Rect(0, 10, 100, 90),
-                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
-    }
-
-    @Test
-    public void testCalculateSnapshotCrop_navBarLeft() {
-        final Rect contentInsets = new Rect(10, 0, 0, 0);
-        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(10, 0, 100, 100),
-                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
-    }
-
-    @Test
-    public void testCalculateSnapshotCrop_navBarRight() {
-        final Rect contentInsets = new Rect(0, 10, 10, 0);
-        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(0, 0, 90, 100),
-                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
-    }
-
-    @Test
-    public void testCalculateSnapshotCrop_waterfall() {
-        final Rect contentInsets = new Rect(5, 10, 5, 10);
-        setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
-        assertEquals(new Rect(5, 0, 95, 90),
-                mSnapshotSurface.calculateSnapshotCrop(contentInsets));
-    }
-
-    @Test
-    public void testCalculateSnapshotFrame() {
-        setupSurface(100, 100);
-        final Rect insets = new Rect(0, 10, 0, 10);
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
-        assertEquals(new Rect(0, 0, 100, 80),
-                mSnapshotSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
-    }
-
-    @Test
-    public void testCalculateSnapshotFrame_navBarLeft() {
-        setupSurface(100, 100);
-        final Rect insets = new Rect(10, 10, 0, 0);
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
-        assertEquals(new Rect(10, 0, 100, 90),
-                mSnapshotSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
-    }
-
-    @Test
-    public void testCalculateSnapshotFrame_waterfall() {
-        setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, new Rect(0, 0, 100, 100));
-        final Rect insets = new Rect(0, 10, 0, 10);
-        mSnapshotSurface.setFrames(new Rect(5, 0, 95, 100), insets);
-        assertEquals(new Rect(0, 0, 90, 90),
-                mSnapshotSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
-    }
-
-    @Test
     public void testDrawStatusBarBackground() {
         setupSurface(100, 100);
         final Rect insets = new Rect(0, 10, 10, 0);
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100));
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, new Rect(0, 0, 50, 100));
         verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
     }
 
@@ -242,11 +97,11 @@
     public void testDrawStatusBarBackground_nullFrame() {
         setupSurface(100, 100);
         final Rect insets = new Rect(0, 10, 10, 0);
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawStatusBarBackground(mockCanvas, null);
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, null /* alreadyDrawnFrame */);
         verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
     }
 
@@ -254,11 +109,11 @@
     public void testDrawStatusBarBackground_nope() {
         setupSurface(100, 100);
         final Rect insets = new Rect(0, 10, 10, 0);
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100));
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, new Rect(0, 0, 100, 100));
         verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
     }
 
@@ -267,11 +122,11 @@
         final Rect insets = new Rect(0, 10, 0, 10);
         setupSurface(100, 100, insets, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                 new Rect(0, 0, 100, 100));
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawNavigationBarBackground(mockCanvas);
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, null /* alreadyDrawnFrame */);
         verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
     }
 
@@ -280,11 +135,11 @@
         final Rect insets = new Rect(10, 10, 0, 0);
         setupSurface(100, 100, insets, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                 new Rect(0, 0, 100, 100));
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawNavigationBarBackground(mockCanvas);
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, null /* alreadyDrawnFrame */);
         verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
     }
 
@@ -293,11 +148,11 @@
         final Rect insets = new Rect(0, 10, 10, 0);
         setupSurface(100, 100, insets, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                 new Rect(0, 0, 100, 100));
-        mSnapshotSurface.setFrames(new Rect(0, 0, 100, 100), insets);
+        mSystemBarBackgroundPainter.setInsets(insets);
         final Canvas mockCanvas = mock(Canvas.class);
         when(mockCanvas.getWidth()).thenReturn(100);
         when(mockCanvas.getHeight()).thenReturn(100);
-        mSnapshotSurface.drawNavigationBarBackground(mockCanvas);
+        mSystemBarBackgroundPainter.drawDecors(mockCanvas, null /* alreadyDrawnFrame */);
         verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
     }
 }
diff --git a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java
index bb2fe1b..84ff40f 100644
--- a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java
+++ b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java
@@ -33,11 +33,15 @@
 import android.content.res.Configuration;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.IWindowManager;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.window.flags.Flags;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -58,6 +62,9 @@
     @Rule
     public final MockitoRule mockito = MockitoJUnit.rule();
 
+    @Rule
+    public SetFlagsRule setFlagsRule = new SetFlagsRule();
+
     @Mock
     private IWindowManager mWindowManagerService;
     @Mock
@@ -161,6 +168,7 @@
         verify(mWindowManagerService).detachWindowContext(mWindowTokenClient);
     }
 
+    @EnableFlags(Flags.FLAG_TRACK_SYSTEM_UI_CONTEXT_BEFORE_WMS)
     @Test
     public void testAttachToDisplayContent_keepTrackWithoutWMS() {
         // WMS is not initialized
diff --git a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
index 00b4f46..d1fbc77c 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LockPatternUtilsTest.java
@@ -31,6 +31,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doNothing;
@@ -44,20 +45,27 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.UserInfo;
+import android.hardware.input.IInputManager;
+import android.hardware.input.InputManagerGlobal;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.platform.test.ravenwood.RavenwoodRule;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
+import android.view.InputDevice;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.widget.flags.Flags;
 
 import com.google.android.collect.Lists;
 
@@ -76,6 +84,8 @@
 public class LockPatternUtilsTest {
     @Rule
     public final RavenwoodRule mRavenwood = new RavenwoodRule();
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private ILockSettings mLockSettings;
     private static final int USER_ID = 1;
@@ -395,4 +405,156 @@
             }
         };
     }
+
+    private InputManagerGlobal.TestSession configureExternalHardwareTest(InputDevice[] devices)
+            throws RemoteException {
+        final Context context = new ContextWrapper(InstrumentationRegistry.getTargetContext());
+        final ILockSettings ils = mock(ILockSettings.class);
+        when(ils.getBoolean(anyString(), anyBoolean(), anyInt())).thenThrow(RemoteException.class);
+        mLockPatternUtils = new LockPatternUtils(context, ils);
+
+        IInputManager inputManagerMock = mock(IInputManager.class);
+
+        int[] deviceIds = new int[devices.length];
+
+        for (int i = 0; i < devices.length; i++) {
+            when(inputManagerMock.getInputDevice(i)).thenReturn(devices[i]);
+        }
+
+        when(inputManagerMock.getInputDeviceIds()).thenReturn(deviceIds);
+        InputManagerGlobal.TestSession session =
+                InputManagerGlobal.createTestSession(inputManagerMock);
+
+        return session;
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_noDevicesAttached() throws RemoteException {
+        InputManagerGlobal.TestSession session = configureExternalHardwareTest(new InputDevice[0]);
+        assertFalse(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_noEnabledDeviceAttached() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder.setEnabled(false);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertFalse(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_withoutHwKeyboard() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder.setEnabled(true).setSources(InputDevice.SOURCE_TOUCHSCREEN);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertFalse(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_withoutFullHwKeyboard() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_KEYBOARD)
+                .setKeyboardType(InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertFalse(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_withHwKeyboardOldDefault() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_KEYBOARD)
+                .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertFalse(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isPinEnhancedPrivacyEnabled_withHwKeyboard() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_KEYBOARD)
+                .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertTrue(mLockPatternUtils.isPinEnhancedPrivacyEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isVisiblePatternEnabled_noDevices() throws RemoteException {
+        InputManagerGlobal.TestSession session = configureExternalHardwareTest(new InputDevice[0]);
+        assertTrue(mLockPatternUtils.isVisiblePatternEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isVisiblePatternEnabled_noEnabledDevices() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder.setEnabled(false);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertTrue(mLockPatternUtils.isVisiblePatternEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isVisiblePatternEnabled_noPointingDevices() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_TOUCHSCREEN);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertTrue(mLockPatternUtils.isVisiblePatternEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isVisiblePatternEnabled_externalPointingDevice() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_CLASS_POINTER);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertFalse(mLockPatternUtils.isVisiblePatternEnabled(USER_ID));
+        session.close();
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_HIDE_LAST_CHAR_WITH_PHYSICAL_INPUT)
+    public void isVisiblePatternEnabled_externalPointingDeviceOldDefault() throws RemoteException {
+        InputDevice.Builder builder = new InputDevice.Builder();
+        builder
+                .setEnabled(true)
+                .setSources(InputDevice.SOURCE_CLASS_POINTER);
+        InputManagerGlobal.TestSession session =
+                configureExternalHardwareTest(new InputDevice[]{builder.build()});
+        assertTrue(mLockPatternUtils.isVisiblePatternEnabled(USER_ID));
+        session.close();
+    }
 }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 2398e71..f136e06 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -125,6 +125,7 @@
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS"/>
         <permission name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER"/>
+        <permission name="android.permission.RESOLVE_COMPONENT_FOR_UID"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.phone">
@@ -609,6 +610,8 @@
         <permission name="android.permission.MANAGE_INTRUSION_DETECTION_STATE" />
         <!-- Permission required for CTS test - KeyguardLockedStateApiTest -->
         <permission name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
+        <!-- Permission required for CTS test - CtsContentProviderMultiUserTest -->
+        <permission name="android.permission.RESOLVE_COMPONENT_FOR_UID"/>
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/BlendModeColorFilter.java b/graphics/java/android/graphics/BlendModeColorFilter.java
index 7caeb42..d4e2373 100644
--- a/graphics/java/android/graphics/BlendModeColorFilter.java
+++ b/graphics/java/android/graphics/BlendModeColorFilter.java
@@ -71,7 +71,7 @@
             return false;
         }
         final BlendModeColorFilter other = (BlendModeColorFilter) object;
-        return other.mMode == mMode;
+        return (other.mMode == mMode && other.mColor == mColor);
     }
 
     @Override
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 2e88514..50c95a9 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1586,6 +1586,18 @@
      * @return         typeface
      */
     public Typeface setTypeface(Typeface typeface) {
+        if (Flags.typefaceRedesignReadonly() && typeface != null
+                && typeface.isVariationInstance()) {
+            Log.w(TAG, "Attempting to set a Typeface on a Paint object that was previously "
+                    + "configured with setFontVariationSettings(). This is no longer supported as "
+                    + "of Target SDK " + Build.VERSION_CODES.BAKLAVA + ". To apply font"
+                    + " variations, call setFontVariationSettings() directly on the Paint object"
+                    + " instead.");
+        }
+        return setTypefaceWithoutWarning(typeface);
+    }
+
+    private Typeface setTypefaceWithoutWarning(Typeface typeface) {
         final long typefaceNative = typeface == null ? 0 : typeface.native_instance;
         nSetTypeface(mNativePaint, typefaceNative);
         mTypeface = typeface;
@@ -2183,7 +2195,7 @@
 
         if (settings == null || settings.length() == 0) {
             mFontVariationSettings = null;
-            setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface,
+            setTypefaceWithoutWarning(Typeface.createFromTypefaceWithVariation(mTypeface,
                       Collections.emptyList()));
             return true;
         }
@@ -2202,7 +2214,8 @@
             return false;
         }
         mFontVariationSettings = settings;
-        setTypeface(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes));
+        setTypefaceWithoutWarning(
+                Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes));
         return true;
     }
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 889a7785..874b847 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -237,6 +237,8 @@
 
     private @IntRange(from = 0, to = FontStyle.FONT_WEIGHT_MAX) final int mWeight;
 
+    private boolean mIsVariationInstance;
+
     // Value for weight and italic. Indicates the value is resolved by font metadata.
     // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
     /** @hide */
@@ -279,6 +281,11 @@
         return mWeight;
     }
 
+    /** @hide */
+    public boolean isVariationInstance() {
+        return mIsVariationInstance;
+    }
+
     /** Returns the typeface's intrinsic style attributes */
     public @Style int getStyle() {
         return mStyle;
@@ -1280,6 +1287,7 @@
         mCleaner = sRegistry.registerNativeAllocation(this, native_instance);
         mStyle = nativeGetStyle(ni);
         mWeight = nativeGetWeight(ni);
+        mIsVariationInstance = nativeIsVariationInstance(ni);
         mSystemFontFamilyName = systemFontFamilyName;
         mDerivedFrom = derivedFrom;
     }
@@ -1698,6 +1706,9 @@
     private static native int  nativeGetWeight(long nativePtr);
 
     @CriticalNative
+    private static native boolean nativeIsVariationInstance(long nativePtr);
+
+    @CriticalNative
     private static native long nativeGetReleaseFunc();
 
     private static native void nativeRegisterGenericFamily(String str, long nativePtr);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationRequestCallback.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationRequestCallback.java
index ea33426..9f978e0 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationRequestCallback.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/RearDisplayPresentationRequestCallback.java
@@ -43,10 +43,7 @@
     public RearDisplayPresentationRequestCallback(@NonNull Context context,
             @NonNull RearDisplayPresentationController rearDisplayPresentationController) {
         mDisplayManager = context.getSystemService(DisplayManager.class);
-        mDisplayManager.registerDisplayListener(mRearDisplayListener,
-                context.getMainThreadHandler(), DisplayManager.EVENT_FLAG_DISPLAY_ADDED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);
-
+        registerDisplayListener(context);
         mRearDisplayPresentationController = rearDisplayPresentationController;
     }
 
@@ -112,4 +109,10 @@
             mRearDisplayPresentationController.startSession(rearDisplay);
         }
     }
+
+    private void registerDisplayListener(Context context) {
+        mDisplayManager.registerDisplayListener(mRearDisplayListener,
+                context.getMainThreadHandler(), DisplayManager.EVENT_TYPE_DISPLAY_ADDED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_CHANGED);
+    }
 }
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 636e3cf..b2ac640 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -32,6 +32,7 @@
             android:name=".desktopmode.DesktopWallpaperActivity"
             android:excludeFromRecents="true"
             android:launchMode="singleInstance"
+            android:showForAllUsers="true"
             android:theme="@style/DesktopWallpaperTheme" />
 
         <activity
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index 5f1fb4b..bbdcbc9 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -171,3 +171,17 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "task_view_repository"
+    namespace: "multitasking"
+    description: "Factor task-view state tracking out of taskviewtransitions"
+    bug: "384976265"
+}
+
+flag {
+    name: "enable_non_default_display_split"
+    namespace: "multitasking"
+    description: "Enables split screen on non default displays"
+    bug: "384999213"
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/Android.bp b/libs/WindowManager/Shell/multivalentTests/Android.bp
index 41d1b5c..eecf199 100644
--- a/libs/WindowManager/Shell/multivalentTests/Android.bp
+++ b/libs/WindowManager/Shell/multivalentTests/Android.bp
@@ -55,6 +55,7 @@
         "truth",
         "flag-junit-base",
         "flag-junit",
+        "testables",
     ],
     auto_gen_config: true,
 }
@@ -77,6 +78,7 @@
         "truth",
         "platform-test-annotations",
         "platform-test-rules",
+        "testables",
     ],
     libs: [
         "android.test.base.stubs.system",
diff --git a/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml b/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
index f8f8338..fd578a9 100644
--- a/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/multivalentTests/AndroidManifest.xml
@@ -3,6 +3,8 @@
 
     <application android:debuggable="true" android:supportsRtl="true" >
         <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.wm.shell.bubbles.bar.BubbleBarAnimationHelperTest$TestActivity"
+            android:exported="true"/>
     </application>
 
     <instrumentation
diff --git a/libs/WindowManager/Shell/multivalentTests/AndroidManifestRobolectric.xml b/libs/WindowManager/Shell/multivalentTests/AndroidManifestRobolectric.xml
index ffcd7d4..bb111db 100644
--- a/libs/WindowManager/Shell/multivalentTests/AndroidManifestRobolectric.xml
+++ b/libs/WindowManager/Shell/multivalentTests/AndroidManifestRobolectric.xml
@@ -1,3 +1,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.wm.shell.multivalenttests">
+    <application>
+        <activity android:name="com.android.wm.shell.bubbles.bar.BubbleBarAnimationHelperTest$TestActivity"
+            android:exported="true"/>
+    </application>
 </manifest>
+
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
index 2b4e541..c62d2a0 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerBubbleBarTest.kt
@@ -35,11 +35,11 @@
 import com.android.wm.shell.Flags
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.TestShellExecutor
-import com.android.wm.shell.WindowManagerShellWrapper
 import com.android.wm.shell.bubbles.Bubbles.SysuiProxy
 import com.android.wm.shell.bubbles.properties.ProdBubbleProperties
 import com.android.wm.shell.bubbles.storage.BubblePersistentRepository
 import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayImeController
 import com.android.wm.shell.common.DisplayInsetsController
 import com.android.wm.shell.common.FloatingContentCoordinator
 import com.android.wm.shell.common.SyncTransactionQueue
@@ -268,7 +268,8 @@
             bubbleDataRepository,
             mock<IStatusBarService>(),
             mock<WindowManager>(),
-            WindowManagerShellWrapper(mainExecutor),
+            mock<DisplayInsetsController>(),
+            mock<DisplayImeController>(),
             mock<UserManager>(),
             mock<LauncherApps>(),
             bubbleLogger,
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskTest.kt
index 680d015..3043e2b 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskTest.kt
@@ -36,10 +36,10 @@
 import com.android.launcher3.icons.BubbleIconFactory
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.TestShellExecutor
-import com.android.wm.shell.WindowManagerShellWrapper
 import com.android.wm.shell.bubbles.properties.BubbleProperties
 import com.android.wm.shell.bubbles.storage.BubblePersistentRepository
 import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayImeController
 import com.android.wm.shell.common.DisplayInsetsController
 import com.android.wm.shell.common.FloatingContentCoordinator
 import com.android.wm.shell.common.SyncTransactionQueue
@@ -141,7 +141,8 @@
                 bubbleDataRepository,
                 mock<IStatusBarService>(),
                 windowManager,
-                WindowManagerShellWrapper(mainExecutor),
+                mock<DisplayInsetsController>(),
+                mock<DisplayImeController>(),
                 mock<UserManager>(),
                 mock<LauncherApps>(),
                 bubbleLogger,
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt
index 0d8f809..957f0ca 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt
@@ -16,14 +16,20 @@
 
 package com.android.wm.shell.bubbles.bar
 
+import android.animation.AnimatorTestRule
+import android.app.Activity
+import android.app.ActivityManager
 import android.content.Context
 import android.graphics.Insets
+import android.graphics.Outline
 import android.graphics.Rect
+import android.os.Bundle
 import android.view.View
 import android.view.ViewGroup
 import android.view.WindowManager
 import android.widget.FrameLayout
-import androidx.core.animation.AnimatorTestRule
+import android.widget.FrameLayout.LayoutParams
+import androidx.test.core.app.ActivityScenario
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -36,27 +42,35 @@
 import com.android.wm.shell.bubbles.BubbleLogger
 import com.android.wm.shell.bubbles.BubbleOverflow
 import com.android.wm.shell.bubbles.BubblePositioner
+import com.android.wm.shell.bubbles.BubbleTaskView
 import com.android.wm.shell.bubbles.DeviceConfig
 import com.android.wm.shell.bubbles.FakeBubbleExpandedViewManager
 import com.android.wm.shell.bubbles.FakeBubbleFactory
-import com.android.wm.shell.bubbles.FakeBubbleTaskViewFactory
+import com.android.wm.shell.taskview.TaskView
+import com.android.wm.shell.taskview.TaskViewTaskController
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.Semaphore
 import java.util.concurrent.TimeUnit
 import org.junit.After
 import org.junit.Before
-import org.junit.ClassRule
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.clearInvocations
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
 
 /** Tests for [BubbleBarAnimationHelper] */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class BubbleBarAnimationHelperTest {
 
-    companion object {
-        @JvmField @ClassRule val animatorTestRule: AnimatorTestRule = AnimatorTestRule()
+    @get:Rule val animatorTestRule: AnimatorTestRule = AnimatorTestRule(this)
+    private lateinit var activityScenario: ActivityScenario<TestActivity>
 
+    companion object {
         const val SCREEN_WIDTH = 2000
         const val SCREEN_HEIGHT = 1000
     }
@@ -75,6 +89,8 @@
     fun setUp() {
         ProtoLog.REQUIRE_PROTOLOGTOOL = false
         ProtoLog.init()
+        activityScenario = ActivityScenario.launch(TestActivity::class.java)
+        activityScenario.onActivity { activity -> container = activity.container }
         val windowManager = context.getSystemService(WindowManager::class.java)
         bubblePositioner = BubblePositioner(context, windowManager)
         bubblePositioner.setShowingInBubbleBar(true)
@@ -94,8 +110,6 @@
         mainExecutor = TestShellExecutor()
         bgExecutor = TestShellExecutor()
 
-        container = FrameLayout(context)
-
         animationHelper = BubbleBarAnimationHelper(context, bubblePositioner)
     }
 
@@ -113,7 +127,7 @@
         val semaphore = Semaphore(0)
         val after = Runnable { semaphore.release() }
 
-        getInstrumentation().runOnMainSync {
+        activityScenario.onActivity {
             animationHelper.animateSwitch(fromBubble, toBubble, after)
             animatorTestRule.advanceTimeBy(1000)
         }
@@ -137,7 +151,7 @@
             .updateHandleColor(/* isRegionDark= */ true, /* animated= */ false)
         val toBubble = createBubble(key = "to").initialize(container)
 
-        getInstrumentation().runOnMainSync {
+        activityScenario.onActivity {
             animationHelper.animateSwitch(fromBubble, toBubble, /* afterAnimation= */ null)
             animatorTestRule.advanceTimeBy(1000)
         }
@@ -148,6 +162,26 @@
     }
 
     @Test
+    fun animateSwitch_bubbleToBubble_updateTaskBounds() {
+        val fromBubble = createBubble("from").initialize(container)
+        val toBubbleTaskController = mock<TaskViewTaskController>()
+        val toBubble = createBubble("to", toBubbleTaskController).initialize(container)
+
+        activityScenario.onActivity {
+            animationHelper.animateSwitch(fromBubble, toBubble) {}
+            // Start the animation, but don't finish
+            animatorTestRule.advanceTimeBy(100)
+        }
+        getInstrumentation().waitForIdleSync()
+        // Clear invocations to ensure that bounds update happens after animation ends
+        clearInvocations(toBubbleTaskController)
+        getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(900) }
+        getInstrumentation().waitForIdleSync()
+
+        verify(toBubbleTaskController).setWindowBounds(any())
+    }
+
+    @Test
     fun animateSwitch_bubbleToOverflow_oldHiddenNewShown() {
         val fromBubble = createBubble(key = "from").initialize(container)
         val overflow = createOverflow().initialize(container)
@@ -155,7 +189,7 @@
         val semaphore = Semaphore(0)
         val after = Runnable { semaphore.release() }
 
-        getInstrumentation().runOnMainSync {
+        activityScenario.onActivity {
             animationHelper.animateSwitch(fromBubble, overflow, after)
             animatorTestRule.advanceTimeBy(1000)
         }
@@ -178,7 +212,7 @@
         val semaphore = Semaphore(0)
         val after = Runnable { semaphore.release() }
 
-        getInstrumentation().runOnMainSync {
+        activityScenario.onActivity {
             animationHelper.animateSwitch(overflow, toBubble, after)
             animatorTestRule.advanceTimeBy(1000)
         }
@@ -193,13 +227,117 @@
         assertThat(toBubble.bubbleBarExpandedView?.isSurfaceZOrderedOnTop).isFalse()
     }
 
-    private fun createBubble(key: String): Bubble {
+    @Test
+    fun animateToRestPosition_updateTaskBounds() {
+        val taskController = mock<TaskViewTaskController>()
+        val bubble = createBubble("key", taskController).initialize(container)
+
+        activityScenario.onActivity {
+            animationHelper.animateExpansion(bubble) {}
+            animatorTestRule.advanceTimeBy(1000)
+        }
+        getInstrumentation().waitForIdleSync()
+        getInstrumentation().runOnMainSync {
+            animationHelper.animateToRestPosition()
+            animatorTestRule.advanceTimeBy(100)
+        }
+        // Clear invocations to ensure that bounds update happens after animation ends
+        clearInvocations(taskController)
+        getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(900) }
+        getInstrumentation().waitForIdleSync()
+
+        verify(taskController).setWindowBounds(any())
+    }
+
+    @Test
+    fun animateExpansion() {
+        val bubble = createBubble(key = "b1").initialize(container)
+        val bbev = bubble.bubbleBarExpandedView!!
+
+        val semaphore = Semaphore(0)
+        val after = Runnable { semaphore.release() }
+
+        activityScenario.onActivity {
+            bbev.onTaskCreated()
+            animationHelper.animateExpansion(bubble, after)
+            animatorTestRule.advanceTimeBy(1000)
+        }
+        getInstrumentation().waitForIdleSync()
+
+        assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+        assertThat(bbev.alpha).isEqualTo(1)
+    }
+
+    @Test
+    fun onImeTopChanged_noOverlap() {
+        val bubble = createBubble(key = "b1").initialize(container)
+        val bbev = bubble.bubbleBarExpandedView!!
+
+        val semaphore = Semaphore(0)
+        val after = Runnable { semaphore.release() }
+
+        activityScenario.onActivity {
+            bbev.onTaskCreated()
+            animationHelper.animateExpansion(bubble, after)
+            animatorTestRule.advanceTimeBy(1000)
+        }
+        getInstrumentation().waitForIdleSync()
+
+        assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+
+        val bbevBottom = bbev.contentBottomOnScreen + bubblePositioner.insets.top
+        activityScenario.onActivity {
+            // notify that the IME top coordinate is greater than the bottom of the expanded view.
+            // there's no overlap so it should not be clipped.
+            animationHelper.onImeTopChanged(bbevBottom * 2)
+        }
+        val outline = Outline()
+        bbev.outlineProvider.getOutline(bbev, outline)
+        assertThat(outline.mRect.bottom).isEqualTo(bbev.height)
+    }
+
+    @Test
+    fun onImeTopChanged_overlapsWithExpandedView() {
+        val bubble = createBubble(key = "b1").initialize(container)
+        val bbev = bubble.bubbleBarExpandedView!!
+
+        val semaphore = Semaphore(0)
+        val after = Runnable { semaphore.release() }
+
+        activityScenario.onActivity {
+            bbev.onTaskCreated()
+            animationHelper.animateExpansion(bubble, after)
+            animatorTestRule.advanceTimeBy(1000)
+        }
+        getInstrumentation().waitForIdleSync()
+
+        assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+
+        activityScenario.onActivity {
+            // notify that the IME top coordinate is less than the bottom of the expanded view,
+            // meaning it overlaps with it so we should be clipping the expanded view.
+            animationHelper.onImeTopChanged(bbev.contentBottomOnScreen - 10)
+        }
+        val outline = Outline()
+        bbev.outlineProvider.getOutline(bbev, outline)
+        assertThat(outline.mRect.bottom).isEqualTo(bbev.height - 10)
+    }
+
+    private fun createBubble(
+        key: String,
+        taskViewTaskController: TaskViewTaskController = mock<TaskViewTaskController>(),
+    ): Bubble {
+        val taskView = TaskView(context, taskViewTaskController)
+        val taskInfo = mock<ActivityManager.RunningTaskInfo>()
+        whenever(taskViewTaskController.taskInfo).thenReturn(taskInfo)
+        val bubbleTaskView = BubbleTaskView(taskView, mainExecutor)
+
         val bubbleBarExpandedView =
             FakeBubbleFactory.createExpandedView(
                 context,
                 bubblePositioner,
                 expandedViewManager,
-                FakeBubbleTaskViewFactory(context, mainExecutor).create(),
+                bubbleTaskView,
                 mainExecutor,
                 bgExecutor,
                 bubbleLogger,
@@ -215,14 +353,24 @@
     }
 
     private fun Bubble.initialize(container: ViewGroup): Bubble {
-        getInstrumentation().runOnMainSync { container.addView(bubbleBarExpandedView) }
+        activityScenario.onActivity { container.addView(bubbleBarExpandedView) }
         // Mark taskView's visible
         bubbleBarExpandedView!!.onContentVisibilityChanged(true)
         return this
     }
 
     private fun BubbleOverflow.initialize(container: ViewGroup): BubbleOverflow {
-        getInstrumentation().runOnMainSync { container.addView(bubbleBarExpandedView) }
+        activityScenario.onActivity { container.addView(bubbleBarExpandedView) }
         return this
     }
+
+    class TestActivity : Activity() {
+        lateinit var container: FrameLayout
+        override fun onCreate(savedInstanceState: Bundle?) {
+            super.onCreate(savedInstanceState)
+            container = FrameLayout(applicationContext)
+            container.layoutParams = LayoutParams(50, 50)
+            setContentView(container)
+        }
+    }
 }
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
index 04c9ffb..9b1645e 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerViewTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.bubbles.bar
 
+import android.animation.AnimatorTestRule
 import android.content.Context
 import android.content.pm.LauncherApps
 import android.graphics.PointF
@@ -25,7 +26,7 @@
 import android.view.MotionEvent
 import android.view.View
 import android.view.WindowManager
-import androidx.core.animation.AnimatorTestRule
+import androidx.core.view.children
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -36,12 +37,11 @@
 import com.android.wm.shell.R
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.TestShellExecutor
-import com.android.wm.shell.WindowManagerShellWrapper
 import com.android.wm.shell.bubbles.Bubble
 import com.android.wm.shell.bubbles.BubbleController
 import com.android.wm.shell.bubbles.BubbleData
 import com.android.wm.shell.bubbles.BubbleDataRepository
-import com.android.wm.shell.bubbles.BubbleEducationController
+import com.android.wm.shell.bubbles.BubbleExpandedViewManager
 import com.android.wm.shell.bubbles.BubbleLogger
 import com.android.wm.shell.bubbles.BubblePositioner
 import com.android.wm.shell.bubbles.Bubbles.SysuiProxy
@@ -53,6 +53,7 @@
 import com.android.wm.shell.bubbles.properties.BubbleProperties
 import com.android.wm.shell.bubbles.storage.BubblePersistentRepository
 import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayImeController
 import com.android.wm.shell.common.DisplayInsetsController
 import com.android.wm.shell.common.FloatingContentCoordinator
 import com.android.wm.shell.common.SyncTransactionQueue
@@ -68,32 +69,31 @@
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
-import org.junit.ClassRule
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
 import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
 
 /** Tests for [BubbleBarLayerView] */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class BubbleBarLayerViewTest {
 
-    companion object {
-        @JvmField @ClassRule val animatorTestRule: AnimatorTestRule = AnimatorTestRule()
-    }
+    @get:Rule val animatorTestRule: AnimatorTestRule = AnimatorTestRule(this)
 
     private val context = ApplicationProvider.getApplicationContext<Context>()
 
     private lateinit var bubbleBarLayerView: BubbleBarLayerView
-
     private lateinit var uiEventLoggerFake: UiEventLoggerFake
-
     private lateinit var bubbleController: BubbleController
-
     private lateinit var bubblePositioner: BubblePositioner
-
-    private lateinit var bubble: Bubble
+    private lateinit var expandedViewManager: BubbleExpandedViewManager
+    private lateinit var mainExecutor: TestShellExecutor
+    private lateinit var bgExecutor: TestShellExecutor
+    private lateinit var bubbleLogger: BubbleLogger
+    private lateinit var testBubblesList: MutableList<Bubble>
 
     @Before
     fun setUp() {
@@ -102,25 +102,20 @@
         PhysicsAnimatorTestUtils.prepareForTest()
 
         uiEventLoggerFake = UiEventLoggerFake()
-        val bubbleLogger = BubbleLogger(uiEventLoggerFake)
+        bubbleLogger = BubbleLogger(uiEventLoggerFake)
 
-        val mainExecutor = TestShellExecutor()
-        val bgExecutor = TestShellExecutor()
+        mainExecutor = TestShellExecutor()
+        bgExecutor = TestShellExecutor()
 
         val windowManager = context.getSystemService(WindowManager::class.java)
 
         bubblePositioner = BubblePositioner(context, windowManager)
         bubblePositioner.setShowingInBubbleBar(true)
 
-        val bubbleData =
-            BubbleData(
-                context,
-                bubbleLogger,
-                bubblePositioner,
-                BubbleEducationController(context),
-                mainExecutor,
-                bgExecutor,
-            )
+        testBubblesList = mutableListOf()
+        val bubbleData = mock<BubbleData>()
+        whenever(bubbleData.bubbles).thenReturn(testBubblesList)
+        whenever(bubbleData.hasBubbles()).thenReturn(!testBubblesList.isEmpty())
 
         bubbleController =
             createBubbleController(
@@ -137,21 +132,7 @@
 
         bubbleBarLayerView = BubbleBarLayerView(context, bubbleController, bubbleData, bubbleLogger)
 
-        val expandedViewManager = FakeBubbleExpandedViewManager(bubbleBar = true, expanded = true)
-        val bubbleTaskView = FakeBubbleTaskViewFactory(context, mainExecutor).create()
-        val bubbleBarExpandedView =
-            FakeBubbleFactory.createExpandedView(
-                context,
-                bubblePositioner,
-                expandedViewManager,
-                bubbleTaskView,
-                mainExecutor,
-                bgExecutor,
-                bubbleLogger,
-            )
-
-        val viewInfo = FakeBubbleFactory.createViewInfo(bubbleBarExpandedView)
-        bubble = FakeBubbleFactory.createChatBubble(context, viewInfo = viewInfo)
+        expandedViewManager = FakeBubbleExpandedViewManager(bubbleBar = true, expanded = true)
     }
 
     @After
@@ -199,7 +180,8 @@
             bubbleDataRepository,
             mock<IStatusBarService>(),
             windowManager,
-            WindowManagerShellWrapper(mainExecutor),
+            mock<DisplayInsetsController>(),
+            mock<DisplayImeController>(),
             mock<UserManager>(),
             mock<LauncherApps>(),
             bubbleLogger,
@@ -221,7 +203,54 @@
     }
 
     @Test
+    fun showExpandedView() {
+        val bubble = createBubble("first")
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(bubble) }
+        waitForExpandedViewAnimation()
+
+        // Scrim, dismiss view and expanded view
+        assertThat(bubbleBarLayerView.childCount).isEqualTo(3)
+        assertThat(bubbleBarLayerView.getChildAt(2)).isEqualTo(bubble.bubbleBarExpandedView)
+    }
+
+    @Test
+    fun twoBubbles_dismissActiveBubble_newBubbleShown() {
+        val firstBubble = createBubble("first")
+        val secondBubble = createBubble("second")
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(firstBubble) }
+        waitForExpandedViewAnimation()
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.removeBubble(firstBubble) {} }
+        // Expanded view is removed when bubble is removed
+        assertThat(firstBubble.bubbleBarExpandedView).isNull()
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(secondBubble) }
+        waitForExpandedViewAnimation()
+
+        assertThat(bubbleBarLayerView.children.count { it is BubbleBarExpandedView }).isEqualTo(1)
+        assertThat(bubbleBarLayerView.children.last()).isEqualTo(secondBubble.bubbleBarExpandedView)
+    }
+
+    @Test
+    fun twoBubbles_switchBubbles_newBubbleShown() {
+        val firstBubble = createBubble("first")
+        val secondBubble = createBubble("second")
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(firstBubble) }
+        waitForExpandedViewAnimation()
+
+        getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(secondBubble) }
+        waitForExpandedViewAnimation()
+
+        assertThat(bubbleBarLayerView.children.count { it is BubbleBarExpandedView }).isEqualTo(1)
+        assertThat(bubbleBarLayerView.children.last()).isEqualTo(secondBubble.bubbleBarExpandedView)
+    }
+
+    @Test
     fun testEventLogging_dismissExpandedViewViaDrag() {
+        val bubble = createBubble("first")
         getInstrumentation().runOnMainSync { bubbleBarLayerView.showExpandedView(bubble) }
         assertThat(bubbleBarLayerView.findViewById<View>(R.id.bubble_bar_handle_view)).isNotNull()
 
@@ -235,6 +264,7 @@
 
     @Test
     fun testEventLogging_dragExpandedViewLeft() {
+        val bubble = createBubble("first")
         bubblePositioner.bubbleBarLocation = BubbleBarLocation.RIGHT
 
         getInstrumentation().runOnMainSync {
@@ -259,6 +289,7 @@
 
     @Test
     fun testEventLogging_dragExpandedViewRight() {
+        val bubble = createBubble("first")
         bubblePositioner.bubbleBarLocation = BubbleBarLocation.LEFT
 
         getInstrumentation().runOnMainSync {
@@ -281,6 +312,27 @@
         assertThat(uiEventLoggerFake.logs[0]).hasBubbleInfo(bubble)
     }
 
+    private fun createBubble(key: String): Bubble {
+        val bubbleTaskView = FakeBubbleTaskViewFactory(context, mainExecutor).create()
+        val bubbleBarExpandedView =
+            FakeBubbleFactory.createExpandedView(
+                context,
+                bubblePositioner,
+                expandedViewManager,
+                bubbleTaskView,
+                mainExecutor,
+                bgExecutor,
+                bubbleLogger,
+            )
+        // Mark visible so we don't wait for task view before animations can start
+        bubbleBarExpandedView.onContentVisibilityChanged(true)
+
+        val viewInfo = FakeBubbleFactory.createViewInfo(bubbleBarExpandedView)
+        return FakeBubbleFactory.createChatBubble(context, key, viewInfo).also {
+            testBubblesList.add(it)
+        }
+    }
+
     private fun leftEdge(): PointF {
         val screenSize = bubblePositioner.availableRect
         return PointF(screenSize.left.toFloat(), screenSize.height() / 2f)
@@ -293,12 +345,12 @@
 
     private fun waitForExpandedViewAnimation() {
         // wait for idle to allow the animation to start
-        getInstrumentation().waitForIdleSync()
-        getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(200) }
+        getInstrumentation().runOnMainSync { animatorTestRule.advanceTimeBy(1000) }
         PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(
             AnimatableScaleMatrix.SCALE_X,
             AnimatableScaleMatrix.SCALE_Y,
         )
+        getInstrumentation().waitForIdleSync()
     }
 
     private fun View.dispatchTouchEvent(eventTime: Long, action: Int, point: PointF) {
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_background.xml
similarity index 62%
copy from packages/SystemUI/res/color/slider_active_track_color.xml
copy to libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_background.xml
index 8ba5e49..003f397 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_background.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ~ Copyright (C) 2024 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +14,14 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+
+    <stroke
+        android:width="2dp"
+        android:color="@android:color/system_primary_fixed" />
+
+    <solid android:color="@android:color/system_primary_fixed" />
+</shape>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_ic_close.xml b/libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_ic_close.xml
new file mode 100644
index 0000000..8b133a4
--- /dev/null
+++ b/libs/WindowManager/Shell/shared/res/drawable/floating_dismiss_ic_close.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+        android:fillColor="@android:color/system_on_primary_fixed"/>
+</vector>
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/libs/WindowManager/Shell/shared/res/values/dimen.xml
similarity index 66%
copy from packages/SystemUI/res/color/slider_active_track_color.xml
copy to libs/WindowManager/Shell/shared/res/values/dimen.xml
index 8ba5e49..0b1f76f 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/libs/WindowManager/Shell/shared/res/values/dimen.xml
@@ -13,7 +13,8 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+
+<resources>
+    <dimen name="floating_dismiss_icon_size">32dp</dimen>
+    <dimen name="floating_dismiss_background_size">96dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 9aba3aa..348f13a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -90,13 +90,15 @@
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
 import com.android.wm.shell.bubbles.properties.BubbleProperties;
 import com.android.wm.shell.bubbles.shortcut.BubbleShortcutHelper;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.ExternalInterfaceBinder;
 import com.android.wm.shell.common.FloatingContentCoordinator;
+import com.android.wm.shell.common.ImeListener;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SingleInstanceRemoteListener;
@@ -106,7 +108,6 @@
 import com.android.wm.shell.draganddrop.DragAndDropController;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
-import com.android.wm.shell.pip.PinnedStackListenerForwarder;
 import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
 import com.android.wm.shell.shared.annotations.ShellMainThread;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
@@ -182,7 +183,8 @@
     @Nullable private final BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
     private final FloatingContentCoordinator mFloatingContentCoordinator;
     private final BubbleDataRepository mDataRepository;
-    private final WindowManagerShellWrapper mWindowManagerShellWrapper;
+    private final DisplayInsetsController mDisplayInsetsController;
+    private final DisplayImeController mDisplayImeController;
     private final UserManager mUserManager;
     private final LauncherApps mLauncherApps;
     private final IStatusBarService mBarService;
@@ -291,7 +293,8 @@
             BubbleDataRepository dataRepository,
             @Nullable IStatusBarService statusBarService,
             WindowManager windowManager,
-            WindowManagerShellWrapper windowManagerShellWrapper,
+            DisplayInsetsController displayInsetsController,
+            DisplayImeController displayImeController,
             UserManager userManager,
             LauncherApps launcherApps,
             BubbleLogger bubbleLogger,
@@ -318,7 +321,8 @@
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE))
                 : statusBarService;
         mWindowManager = windowManager;
-        mWindowManagerShellWrapper = windowManagerShellWrapper;
+        mDisplayInsetsController = displayInsetsController;
+        mDisplayImeController = displayImeController;
         mUserManager = userManager;
         mFloatingContentCoordinator = floatingContentCoordinator;
         mDataRepository = dataRepository;
@@ -403,11 +407,15 @@
             mMainExecutor.execute(() -> removeBubble(bubble.getKey(), DISMISS_INVALID_INTENT));
         });
 
-        try {
-            mWindowManagerShellWrapper.addPinnedStackListener(new BubblesImeListener());
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
+        BubblesImeListener bubblesImeListener =
+                new BubblesImeListener(mDisplayController, mContext.getDisplayId());
+        // the insets controller is notified whenever the IME visibility changes whether the IME is
+        // requested by a bubbled task or non-bubbled task. in the latter case, we need to update
+        // the position of the stack to avoid overlapping with the IME.
+        mDisplayInsetsController.addInsetsChangedListener(mContext.getDisplayId(),
+                bubblesImeListener);
+        // the ime controller is notified when the IME is requested only by a bubbled task.
+        mDisplayImeController.addPositionProcessor(bubblesImeListener);
 
         mBubbleData.setCurrentUserId(mCurrentUserId);
 
@@ -2515,16 +2523,57 @@
         return contextForUser.getPackageManager();
     }
 
-    /** PinnedStackListener that dispatches IME visibility updates to the stack. */
-    //TODO(b/170442945): Better way to do this / insets listener?
-    private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedTaskListener {
+    /** {@link ImeListener} that dispatches IME visibility updates to the stack. */
+    private class BubblesImeListener extends ImeListener implements
+            DisplayImeController.ImePositionProcessor {
+
+        BubblesImeListener(DisplayController displayController, int displayId) {
+            super(displayController, displayId);
+        }
+
         @Override
-        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
-            mBubblePositioner.setImeVisible(imeVisible, imeHeight);
+        protected void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+            if (getDisplayId() != mContext.getDisplayId()) {
+                return;
+            }
+            // the imeHeight here is actually the ime inset; it only includes the part of the ime
+            // that overlaps with the Bubbles window. adjust it to include the bottom screen inset,
+            // so we have the total height of the ime.
+            int totalImeHeight = imeHeight + mBubblePositioner.getInsets().bottom;
+            mBubblePositioner.setImeVisible(imeVisible, totalImeHeight);
             if (mStackView != null) {
                 mStackView.setImeVisible(imeVisible);
             }
         }
+
+        @Override
+        public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
+                boolean showing, boolean isFloating, SurfaceControl.Transaction t) {
+            if (mContext.getDisplayId() != displayId) {
+                return IME_ANIMATION_DEFAULT;
+            }
+
+            if (showing) {
+                mBubblePositioner.setImeVisible(true, hiddenTop - shownTop);
+            } else {
+                mBubblePositioner.setImeVisible(false, 0);
+            }
+            if (mStackView != null) {
+                mStackView.setImeVisible(showing);
+            }
+
+            return IME_ANIMATION_DEFAULT;
+        }
+
+        @Override
+        public void onImePositionChanged(int displayId, int imeTop, SurfaceControl.Transaction t) {
+            if (mContext.getDisplayId() != displayId) {
+                return;
+            }
+            if (mLayerView != null) {
+                mLayerView.onImeTopChanged(imeTop);
+            }
+        }
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
index de85d9a..1a61793 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblePositioner.java
@@ -67,6 +67,11 @@
     private @Surface.Rotation int mRotation = Surface.ROTATION_0;
     private Insets mInsets;
     private boolean mImeVisible;
+    /**
+     * The height of the IME excluding the bottom inset. If the IME is 100 pixels tall and we have
+     * 20 pixels bottom inset, the IME height is adjusted to 80 to represent the overlap with the
+     * Bubbles window.
+     */
     private int mImeHeight;
     private Rect mPositionRect;
     private int mDefaultMaxBubbles;
@@ -336,10 +341,16 @@
         return mImeVisible;
     }
 
-    /** Sets whether the IME is visible. **/
+    /**
+     * Sets whether the IME is visible and its height.
+     *
+     * @param visible whether the IME is visible
+     * @param height the total height of the IME from the bottom of the physical screen
+     **/
     public void setImeVisible(boolean visible, int height) {
         mImeVisible = visible;
-        mImeHeight = height;
+        // adjust the IME to account for the height as seen by the Bubbles window
+        mImeHeight = visible ? Math.max(height - getInsets().bottom, 0) : 0;
     }
 
     private int getExpandedViewLargeScreenInsetFurthestEdge(boolean isOverflow) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissViewExt.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissViewExt.kt
index 00a8172..2f0b62c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissViewExt.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissViewExt.kt
@@ -19,16 +19,17 @@
 
 import com.android.wm.shell.R
 import com.android.wm.shell.shared.bubbles.DismissView
+import com.android.wm.shell.shared.R as SharedR
 
 fun DismissView.setup() {
     setup(DismissView.Config(
             dismissViewResId = R.id.dismiss_view,
-            targetSizeResId = R.dimen.dismiss_circle_size,
-            iconSizeResId = R.dimen.dismiss_target_x_size,
+            targetSizeResId = SharedR.dimen.floating_dismiss_background_size,
+            iconSizeResId = SharedR.dimen.floating_dismiss_icon_size,
             bottomMarginResId = R.dimen.floating_dismiss_bottom_margin,
             floatingGradientHeightResId = R.dimen.floating_dismiss_gradient_height,
             floatingGradientColorResId = android.R.color.system_neutral1_900,
-            backgroundResId = R.drawable.dismiss_circle_background,
-            iconResId = R.drawable.pip_ic_close_white
+            backgroundResId = SharedR.drawable.floating_dismiss_background,
+            iconResId = SharedR.drawable.floating_dismiss_ic_close,
     ))
 }
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
index 3e8a9b6..de6d1f6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelper.java
@@ -30,6 +30,8 @@
 import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED;
 import static com.android.wm.shell.shared.animation.Interpolators.EMPHASIZED_DECELERATE;
 
+import static java.lang.Math.max;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -375,7 +377,6 @@
         return animator;
     }
 
-
     /**
      * Animate the expanded bubble when it is being dragged
      */
@@ -463,6 +464,7 @@
                 super.onAnimationEnd(animation);
                 bbev.resetPivot();
                 bbev.setDragging(false);
+                updateExpandedView(bbev);
             }
         });
         startNewAnimator(animatorSet);
@@ -585,6 +587,18 @@
         }
     }
 
+    /** Handles IME position changes. */
+    public void onImeTopChanged(int imeTop) {
+        BubbleBarExpandedView bbev = getExpandedView();
+        if (bbev == null) {
+            Log.w(TAG, "Bubble bar expanded view was null when IME top changed");
+            return;
+        }
+        int bbevBottom = bbev.getContentBottomOnScreen();
+        int clip = max(bbevBottom - imeTop, 0);
+        bbev.updateBottomClip(clip);
+    }
+
     private @Nullable BubbleBarExpandedView getExpandedView() {
         BubbleViewProvider bubble = mExpandedBubble;
         if (bubble != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
index 65c929a..e073b02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedView.java
@@ -137,6 +137,7 @@
     private Executor mBackgroundExecutor;
     private final Rect mSampleRect = new Rect();
     private final int[] mLoc = new int[2];
+    private final Rect mTempBounds = new Rect();
 
     /** Height of the caption inset at the top of the TaskView */
     private int mCaptionHeight;
@@ -161,6 +162,9 @@
     private boolean mIsAnimating;
     private boolean mIsDragging;
 
+    private boolean mIsClipping = false;
+    private int mBottomClip = 0;
+
     /** An enum value that tracks the visibility state of the task view */
     private enum TaskViewVisibilityState {
         /** The task view is going away, and we're waiting for the surface to be destroyed. */
@@ -203,7 +207,8 @@
         setOutlineProvider(new ViewOutlineProvider() {
             @Override
             public void getOutline(View view, Outline outline) {
-                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mCurrentCornerRadius);
+                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight() - mBottomClip,
+                        mCurrentCornerRadius);
             }
         });
         // Set a touch sink to ensure that clicks on the caption area do not propagate to the parent
@@ -661,6 +666,52 @@
         }
     }
 
+    /** The y coordinate of the bottom of the expanded view. */
+    public int getContentBottomOnScreen() {
+        if (mOverflowView != null) {
+            mOverflowView.getBoundsOnScreen(mTempBounds);
+        }
+        if (mTaskView != null) {
+            mTaskView.getBoundsOnScreen(mTempBounds);
+        }
+        // return the bottom of the content rect, adjusted for insets so the result is in screen
+        // coordinate
+        return mTempBounds.bottom + mPositioner.getInsets().top;
+    }
+
+    /** Update the amount by which to clip the expanded view at the bottom. */
+    public void updateBottomClip(int bottomClip) {
+        mBottomClip = bottomClip;
+        onClipUpdate();
+    }
+
+    private void onClipUpdate() {
+        if (mBottomClip == 0) {
+            if (mIsClipping) {
+                mIsClipping = false;
+                if (mTaskView != null) {
+                    mTaskView.setClipBounds(null);
+                    mTaskView.setEnableSurfaceClipping(false);
+                }
+                invalidateOutline();
+            }
+        } else {
+            if (!mIsClipping) {
+                mIsClipping = true;
+                if (mTaskView != null) {
+                    mTaskView.setEnableSurfaceClipping(true);
+                }
+            }
+            invalidateOutline();
+            if (mTaskView != null) {
+                Rect clipBounds = new Rect(0, 0,
+                        mTaskView.getWidth(),
+                        mTaskView.getHeight() - mBottomClip);
+                mTaskView.setClipBounds(clipBounds);
+            }
+        }
+    }
+
     private void recreateRegionSamplingHelper() {
         if (mRegionSamplingHelper != null) {
             mRegionSamplingHelper.stopAndDestroy();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
index 425afbe..eaa0bd2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarLayerView.java
@@ -184,7 +184,7 @@
         }
         BubbleViewProvider previousBubble = null;
         if (mExpandedBubble != null && !b.getKey().equals(mExpandedBubble.getKey())) {
-            if (mIsExpanded) {
+            if (mIsExpanded && mExpandedBubble.getBubbleBarExpandedView() != null) {
                 // Previous expanded view open, keep it visible to animate the switch
                 previousBubble = mExpandedBubble;
             } else {
@@ -424,6 +424,13 @@
         }
     }
 
+    /** Handles IME position changes. */
+    public void onImeTopChanged(int imeTop) {
+        if (mIsExpanded) {
+            mAnimationHelper.onImeTopChanged(imeTop);
+        }
+    }
+
     /**
      * Log the event only if {@link #mExpandedBubble} is a {@link Bubble}.
      * <p>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index c74bf53..eb1e727 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -419,8 +419,12 @@
                 // already (e.g., when focussing an editText in activity B, while and editText in
                 // activity A is focussed), we will not get a call of #insetsControlChanged, and
                 // therefore have to start the show animation from here
-                startAnimation(mImeRequestedVisible /* show */, false /* forceRestart */,
-                        statsToken);
+                if (visible || mImeShowing) {
+                    // only start the animation if we're either already showing or becoming visible.
+                    // otherwise starting another hide animation causes flickers.
+                    startAnimation(mImeRequestedVisible /* show */, false /* forceRestart */,
+                            statsToken);
+                }
 
                 // In case of a hide, the statsToken should not been send yet (as the animation
                 // is still ongoing). It will be sent at the end of the animation
@@ -643,7 +647,9 @@
                         t.setPosition(animatingLeash, x, endY);
                         t.setAlpha(animatingLeash, 1.f);
                     }
-                    dispatchEndPositioning(mDisplayId, mCancelled, t);
+                    if (!android.view.inputmethod.Flags.refactorInsetsController()) {
+                        dispatchEndPositioning(mDisplayId, mCancelled, t);
+                    }
                     if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
                         ImeTracker.forLogging().onProgress(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
@@ -659,6 +665,14 @@
                         ImeTracker.forLogging().onCancelled(mStatsToken,
                                 ImeTracker.PHASE_WM_ANIMATION_RUNNING);
                     }
+                    if (android.view.inputmethod.Flags.refactorInsetsController()) {
+                        // In split screen, we also set {@link
+                        // WindowContainer#mExcludeInsetsTypes} but this should only happen after
+                        // the IME client visibility was set. Otherwise the insets will we
+                        // dispatched too early, and we get a flicker. Thus, only dispatching it
+                        // after reporting that the IME is hidden to system server.
+                        dispatchEndPositioning(mDisplayId, mCancelled, t);
+                    }
                     if (DEBUG_IME_VISIBILITY) {
                         EventLog.writeEvent(IMF_IME_REMOTE_ANIM_END,
                                 mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
@@ -713,6 +727,10 @@
      * Allows other things to synchronize with the ime position
      */
     public interface ImePositionProcessor {
+
+        /** Default animation flags. */
+        int IME_ANIMATION_DEFAULT = 0;
+
         /**
          * Indicates that ime shouldn't animate alpha. It will always be opaque. Used when stuff
          * behind the IME shouldn't be visible (for example during split-screen adjustment where
@@ -722,6 +740,7 @@
 
         /** @hide */
         @IntDef(prefix = {"IME_ANIMATION_"}, value = {
+                IME_ANIMATION_DEFAULT,
                 IME_ANIMATION_NO_ALPHA,
         })
         @interface ImeAnimationFlags {
@@ -748,7 +767,7 @@
         @ImeAnimationFlags
         default int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
                 boolean showing, boolean isFloating, SurfaceControl.Transaction t) {
-            return 0;
+            return IME_ANIMATION_DEFAULT;
         }
 
         /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ImeListener.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ImeListener.kt
index a34d7be..8851b6a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ImeListener.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ImeListener.kt
@@ -22,8 +22,8 @@
 import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener
 
 abstract class ImeListener(
-    private val mDisplayController: DisplayController,
-    private val mDisplayId: Int
+    private val displayController: DisplayController,
+    val displayId: Int
 ) : OnInsetsChangedListener {
     // The last insets state
     private val mInsetsState = InsetsState()
@@ -36,17 +36,11 @@
 
         // Get the stable bounds that account for display cutout and system bars to calculate the
         // relative IME height
-        val layout = mDisplayController.getDisplayLayout(mDisplayId)
-        if (layout == null) {
-            return
-        }
+        val layout = displayController.getDisplayLayout(displayId) ?: return
         layout.getStableBounds(mTmpBounds)
 
-        val wasVisible = getImeVisibilityAndHeight(mInsetsState).first
-        val oldHeight = getImeVisibilityAndHeight(mInsetsState).second
-
-        val isVisible = getImeVisibilityAndHeight(insetsState).first
-        val newHeight = getImeVisibilityAndHeight(insetsState).second
+        val (wasVisible, oldHeight) = getImeVisibilityAndHeight(mInsetsState)
+        val (isVisible, newHeight) = getImeVisibilityAndHeight(insetsState)
 
         mInsetsState.set(insetsState, true)
         if (wasVisible != isVisible || oldHeight != newHeight) {
@@ -54,8 +48,7 @@
         }
     }
 
-    private fun getImeVisibilityAndHeight(
-            insetsState: InsetsState): Pair<Boolean, Int> {
+    private fun getImeVisibilityAndHeight(insetsState: InsetsState): Pair<Boolean, Int> {
         val source = insetsState.peekSource(InsetsSource.ID_IME)
         val frame = if (source != null && source.isVisible) source.frame else null
         val height = if (frame != null) mTmpBounds.bottom - frame.top else 0
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 21c44c9..4bcec70 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -571,9 +571,9 @@
             // For flexible split, expand app offscreen as well
             if (mDividerSnapAlgorithm.areOffscreenRatiosSupported()) {
                 if (position <= mDividerSnapAlgorithm.getMiddleTarget().position) {
-                    bounds1.top = bounds1.bottom - bounds2.width();
+                    bounds1.top = bounds1.bottom - bounds2.height();
                 } else {
-                    bounds2.bottom = bounds2.top + bounds1.width();
+                    bounds2.bottom = bounds2.top + bounds1.height();
                 }
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index fe6066c..b796b41 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager.RunningTaskInfo;
 import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Context;
@@ -59,6 +60,7 @@
 import com.android.wm.shell.sysui.KeyguardChangeListener;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.FocusTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 
 import dagger.Lazy;
@@ -196,6 +198,9 @@
     private final CompatUIStatusManager mCompatUIStatusManager;
 
     @NonNull
+    private final FocusTransitionObserver mFocusTransitionObserver;
+
+    @NonNull
     private final Optional<DesktopUserRepositories> mDesktopUserRepositories;
 
     public CompatUIController(@NonNull Context context,
@@ -212,7 +217,8 @@
             @NonNull CompatUIShellCommandHandler compatUIShellCommandHandler,
             @NonNull AccessibilityManager accessibilityManager,
             @NonNull CompatUIStatusManager compatUIStatusManager,
-            @NonNull Optional<DesktopUserRepositories> desktopUserRepositories) {
+            @NonNull Optional<DesktopUserRepositories> desktopUserRepositories,
+            @NonNull FocusTransitionObserver focusTransitionObserver) {
         mContext = context;
         mShellController = shellController;
         mDisplayController = displayController;
@@ -229,6 +235,7 @@
                 DISAPPEAR_DELAY_MS, flags);
         mCompatUIStatusManager = compatUIStatusManager;
         mDesktopUserRepositories = desktopUserRepositories;
+        mFocusTransitionObserver = focusTransitionObserver;
         shellInit.addInitCallback(this::onInit, this);
     }
 
@@ -405,7 +412,8 @@
         // start tracking the buttons visibility for this task.
         if (mTopActivityTaskId != taskInfo.taskId
                 && !taskInfo.isTopActivityTransparent
-                && taskInfo.isVisible && taskInfo.isFocused) {
+                && taskInfo.isVisible
+                && mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)) {
             mTopActivityTaskId = taskInfo.taskId;
             setHasShownUserAspectRatioSettingsButton(false);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayout.java
index b141beb..1cc58c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/UserAspectRatioSettingsLayout.java
@@ -32,6 +32,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.window.flags.Flags;
 import com.android.wm.shell.R;
 
 /**
@@ -172,6 +173,9 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 view.setVisibility(View.GONE);
+                if (Flags.releaseUserAspectRatioWm()) {
+                    mWindowManager.release();
+                }
             }
         });
         fadeOut.start();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 6c805c8..eab7f6c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -272,7 +272,8 @@
             @NonNull CompatUIState compatUIState,
             @NonNull CompatUIComponentIdGenerator componentIdGenerator,
             @NonNull CompatUIComponentFactory compatUIComponentFactory,
-            CompatUIStatusManager compatUIStatusManager) {
+            CompatUIStatusManager compatUIStatusManager,
+            @NonNull FocusTransitionObserver focusTransitionObserver) {
         if (!context.getResources().getBoolean(R.bool.config_enableCompatUIController)) {
             return Optional.empty();
         }
@@ -297,7 +298,8 @@
                         compatUIShellCommandHandler.get(),
                         accessibilityManager.get(),
                         compatUIStatusManager,
-                        desktopUserRepositories));
+                        desktopUserRepositories,
+                        focusTransitionObserver));
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index ace7f07..d8c7f4c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -47,7 +47,6 @@
 import com.android.window.flags.Flags;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.activityembedding.ActivityEmbeddingController;
 import com.android.wm.shell.apptoweb.AppToWebGenericLinksParser;
 import com.android.wm.shell.apptoweb.AssistContentRequester;
@@ -100,6 +99,7 @@
 import com.android.wm.shell.desktopmode.ToggleResizeDesktopTaskTransitionHandler;
 import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
 import com.android.wm.shell.desktopmode.compatui.SystemModalsTransitionHandler;
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider;
 import com.android.wm.shell.desktopmode.education.AppHandleEducationController;
 import com.android.wm.shell.desktopmode.education.AppHandleEducationFilter;
 import com.android.wm.shell.desktopmode.education.AppToWebEducationController;
@@ -232,7 +232,8 @@
             FloatingContentCoordinator floatingContentCoordinator,
             IStatusBarService statusBarService,
             WindowManager windowManager,
-            WindowManagerShellWrapper windowManagerShellWrapper,
+            DisplayInsetsController displayInsetsController,
+            DisplayImeController displayImeController,
             UserManager userManager,
             LauncherApps launcherApps,
             TaskStackListenerImpl taskStackListener,
@@ -264,7 +265,8 @@
                         new BubblePersistentRepository(context)),
                 statusBarService,
                 windowManager,
-                windowManagerShellWrapper,
+                displayInsetsController,
+                displayImeController,
                 userManager,
                 launcherApps,
                 logger,
@@ -733,7 +735,8 @@
             FocusTransitionObserver focusTransitionObserver,
             DesktopModeEventLogger desktopModeEventLogger,
             DesktopModeUiEventLogger desktopModeUiEventLogger,
-            DesktopTilingDecorViewModel desktopTilingDecorViewModel) {
+            DesktopTilingDecorViewModel desktopTilingDecorViewModel,
+            DesktopWallpaperActivityTokenProvider desktopWallpaperActivityTokenProvider) {
         return new DesktopTasksController(
                 context,
                 shellInit,
@@ -764,7 +767,8 @@
                 mainHandler,
                 desktopModeEventLogger,
                 desktopModeUiEventLogger,
-                desktopTilingDecorViewModel);
+                desktopTilingDecorViewModel,
+                desktopWallpaperActivityTokenProvider);
     }
 
     @WMSingleton
@@ -1092,6 +1096,7 @@
             ShellTaskOrganizer shellTaskOrganizer,
             Optional<DesktopMixedTransitionHandler> desktopMixedTransitionHandler,
             Optional<BackAnimationController> backAnimationController,
+            DesktopWallpaperActivityTokenProvider desktopWallpaperActivityTokenProvider,
             ShellInit shellInit) {
         return desktopUserRepositories.flatMap(
                 repository ->
@@ -1103,6 +1108,7 @@
                                         shellTaskOrganizer,
                                         desktopMixedTransitionHandler.get(),
                                         backAnimationController.get(),
+                                        desktopWallpaperActivityTokenProvider,
                                         shellInit)));
     }
 
@@ -1306,6 +1312,12 @@
         return new DesktopModeUiEventLogger(uiEventLogger, packageManager);
     }
 
+    @WMSingleton
+    @Provides
+    static DesktopWallpaperActivityTokenProvider provideDesktopWallpaperActivityTokenProvider() {
+        return new DesktopWallpaperActivityTokenProvider();
+    }
+
     //
     // Drag and drop
     //
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index d404634..996d71c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -426,7 +426,7 @@
 
     private fun isWallpaperActivityClosing(info: TransitionInfo) =
         info.changes.any { change ->
-            change.mode == TRANSIT_CLOSE &&
+            TransitionUtil.isClosingMode(change.mode) &&
                 change.taskInfo != null &&
                 DesktopWallpaperActivity.isWallpaperTask(change.taskInfo!!)
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
index ff6fb59..ceef699 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -541,6 +541,9 @@
             TASK_FINISHED(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__TASK_FINISHED),
             SCREEN_OFF(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF),
             TASK_MINIMIZED(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__TASK_MINIMIZED),
+            TASK_MOVED_TO_BACK(
+                FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__TASK_MOVED_TO_BACK
+            ),
         }
 
         /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
index dfa2d9b..e975b58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserver.kt
@@ -38,7 +38,9 @@
 import com.android.internal.protolog.ProtoLog
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT
@@ -236,6 +238,7 @@
         ) {
             // Sessions is finishing, log task updates followed by an exit event
             identifyAndLogTaskUpdates(
+                transitionInfo,
                 preTransitionVisibleFreeformTasks,
                 postTransitionVisibleFreeformTasks,
             )
@@ -252,12 +255,14 @@
             desktopModeEventLogger.logSessionEnter(getEnterReason(transitionInfo))
 
             identifyAndLogTaskUpdates(
+                transitionInfo,
                 preTransitionVisibleFreeformTasks,
                 postTransitionVisibleFreeformTasks,
             )
         } else if (isSessionActive) {
             // Session is neither starting, nor finishing, log task updates if there are any
             identifyAndLogTaskUpdates(
+                transitionInfo,
                 preTransitionVisibleFreeformTasks,
                 postTransitionVisibleFreeformTasks,
             )
@@ -270,6 +275,7 @@
 
     /** Compare the old and new state of taskInfos and identify and log the changes */
     private fun identifyAndLogTaskUpdates(
+        transitionInfo: TransitionInfo,
         preTransitionVisibleFreeformTasks: SparseArray<TaskInfo>,
         postTransitionVisibleFreeformTasks: SparseArray<TaskInfo>,
     ) {
@@ -304,9 +310,19 @@
         // find old tasks that were removed
         preTransitionVisibleFreeformTasks.forEach { taskId, taskInfo ->
             if (!postTransitionVisibleFreeformTasks.containsKey(taskId)) {
-                desktopModeEventLogger.logTaskRemoved(
-                    buildTaskUpdateForTask(taskInfo, postTransitionVisibleFreeformTasks.size())
-                )
+                val minimizeReason =
+                    if (transitionInfo.type == Transitions.TRANSIT_MINIMIZE) {
+                        MinimizeReason.MINIMIZE_BUTTON
+                    } else {
+                        null
+                    }
+                val taskUpdate =
+                    buildTaskUpdateForTask(
+                        taskInfo,
+                        postTransitionVisibleFreeformTasks.size(),
+                        minimizeReason,
+                    )
+                desktopModeEventLogger.logTaskRemoved(taskUpdate)
                 Trace.setCounter(
                     Trace.TRACE_TAG_WINDOW_MANAGER,
                     VISIBLE_TASKS_COUNTER_NAME,
@@ -320,7 +336,11 @@
         }
     }
 
-    private fun buildTaskUpdateForTask(taskInfo: TaskInfo, visibleTasks: Int): TaskUpdate {
+    private fun buildTaskUpdateForTask(
+        taskInfo: TaskInfo,
+        visibleTasks: Int,
+        minimizeReason: MinimizeReason? = null,
+    ): TaskUpdate {
         val screenBounds = taskInfo.configuration.windowConfiguration.bounds
         val positionInParent = taskInfo.positionInParent
         return TaskUpdate(
@@ -331,6 +351,7 @@
             taskX = positionInParent.x,
             taskY = positionInParent.y,
             visibleTaskCount = visibleTasks,
+            minimizeReason = minimizeReason,
         )
     }
 
@@ -343,7 +364,7 @@
                 ||
                     (transitionInfo.type == WindowManager.TRANSIT_TO_BACK &&
                         wasPreviousTransitionExitByScreenOff) -> EnterReason.SCREEN_ON
-                transitionInfo.type == Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP ->
+                transitionInfo.type == TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP ->
                     EnterReason.APP_HANDLE_DRAG
                 transitionInfo.type == TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON ->
                     EnterReason.APP_HANDLE_MENU_BUTTON
@@ -384,12 +405,17 @@
                 wasPreviousTransitionExitByScreenOff = true
                 ExitReason.SCREEN_OFF
             }
+            // TODO(b/384490301): differentiate back gesture / button exit from clicking the close
+            // button located in the window top corner.
+            transitionInfo.type == WindowManager.TRANSIT_TO_BACK -> ExitReason.TASK_MOVED_TO_BACK
             transitionInfo.type == WindowManager.TRANSIT_CLOSE -> ExitReason.TASK_FINISHED
             transitionInfo.type == TRANSIT_EXIT_DESKTOP_MODE_TASK_DRAG -> ExitReason.DRAG_TO_EXIT
             transitionInfo.type == TRANSIT_EXIT_DESKTOP_MODE_HANDLE_MENU_BUTTON ->
                 ExitReason.APP_HANDLE_MENU_BUTTON_EXIT
+
             transitionInfo.type == TRANSIT_EXIT_DESKTOP_MODE_KEYBOARD_SHORTCUT ->
                 ExitReason.KEYBOARD_SHORTCUT_EXIT
+
             transitionInfo.isExitToRecentsTransition() -> ExitReason.RETURN_HOME_OR_OVERVIEW
             transitionInfo.type == Transitions.TRANSIT_MINIMIZE -> ExitReason.TASK_MINIMIZED
             else -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTransitionTypes.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTransitionTypes.kt
index 9b3caca..2a10edb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTransitionTypes.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTransitionTypes.kt
@@ -35,6 +35,18 @@
     const val TRANSIT_EXIT_DESKTOP_MODE_KEYBOARD_SHORTCUT = TRANSIT_DESKTOP_MODE_TYPES + 7
     const val TRANSIT_EXIT_DESKTOP_MODE_UNKNOWN = TRANSIT_DESKTOP_MODE_TYPES + 8
 
+    /** Transition type for starting the drag to desktop mode. */
+    const val TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP = TRANSIT_DESKTOP_MODE_TYPES + 9
+
+    /** Transition type for finalizing the drag to desktop mode. */
+    const val TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP = TRANSIT_DESKTOP_MODE_TYPES + 10
+
+    /** Transition type to cancel the drag to desktop mode. */
+    const val TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP = TRANSIT_DESKTOP_MODE_TYPES + 11
+
+    /** Transition type to animate the toggle resize between the max and default desktop sizes. */
+    const val TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE = TRANSIT_DESKTOP_MODE_TYPES + 12
+
     /** Return whether the [TransitionType] corresponds to a transition to enter desktop mode. */
     @JvmStatic
     fun @receiver:TransitionType Int.isEnterDesktopModeTransition(): Boolean {
@@ -92,4 +104,18 @@
             else -> TRANSIT_EXIT_DESKTOP_MODE_UNKNOWN
         }
     }
+
+    /**
+     * Returns a string representing the [TransitionType]. If not supported, returns an empty
+     * string.
+     */
+    @JvmStatic
+    fun transitTypeToString(transitType: Int): String =
+        when (transitType) {
+            TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP -> "DESKTOP_MODE_START_DRAG_TO_DESKTOP"
+            TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP -> "DESKTOP_MODE_END_DRAG_TO_DESKTOP"
+            TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP -> "DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP"
+            TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE -> "DESKTOP_MODE_TOGGLE_RESIZE"
+            else -> ""
+        }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
index 606a729..9019134 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
@@ -82,7 +82,7 @@
                         // For portrait resizeable activities, respect apps fullscreen width but
                         // apply ideal size height.
                         Size(
-                            taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth,
+                            taskInfo.appCompatTaskInfo.topActivityAppBounds.width(),
                             idealSize.height,
                         )
                     } else {
@@ -104,7 +104,7 @@
                         // apply custom app width.
                         Size(
                             customPortraitWidthForLandscapeApp,
-                            taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight,
+                            taskInfo.appCompatTaskInfo.topActivityAppBounds.height(),
                         )
                     } else {
                         // For portrait resizeable activities, simply apply ideal size.
@@ -196,13 +196,8 @@
 
 /** Calculates the aspect ratio of an activity from its fullscreen bounds. */
 fun calculateAspectRatio(taskInfo: RunningTaskInfo): Float {
-    val appLetterboxWidth = taskInfo.appCompatTaskInfo.topActivityLetterboxAppWidth
-    val appLetterboxHeight = taskInfo.appCompatTaskInfo.topActivityLetterboxAppHeight
-    if (taskInfo.appCompatTaskInfo.isTopActivityLetterboxed || !taskInfo.canChangeAspectRatio) {
-        return maxOf(appLetterboxWidth, appLetterboxHeight) /
-            minOf(appLetterboxWidth, appLetterboxHeight).toFloat()
-    }
-    val appBounds = taskInfo.configuration.windowConfiguration.appBounds ?: return 1f
+    if (taskInfo.appCompatTaskInfo.topActivityAppBounds.isEmpty) return 1f
+    val appBounds = taskInfo.appCompatTaskInfo.topActivityAppBounds
     return maxOf(appBounds.height(), appBounds.width()) /
         minOf(appBounds.height(), appBounds.width()).toFloat()
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index c5b570dd..d306664 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -23,7 +23,6 @@
 import android.util.SparseArray
 import android.view.Display.INVALID_DISPLAY
 import android.window.DesktopModeFlags
-import android.window.WindowContainerToken
 import androidx.core.util.forEach
 import androidx.core.util.keyIterator
 import androidx.core.util.valueIterator
@@ -90,9 +89,6 @@
         }
     }
 
-    /* Current wallpaper activity token to remove wallpaper activity when last task is removed. */
-    var wallpaperActivityToken: WindowContainerToken? = null
-
     private val activeTasksListeners = ArraySet<ActiveTasksListener>()
     private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>()
 
@@ -549,7 +545,6 @@
                 "${innerPrefix}topTransparentFullscreenTaskId=" +
                     "${data.topTransparentFullscreenTaskId}"
             )
-            pw.println("${innerPrefix}wallpaperActivityToken=$wallpaperActivityToken")
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index a3d3a90..4e7cba2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -95,6 +95,7 @@
 import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION
 import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION
 import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
 import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler
 import com.android.wm.shell.draganddrop.DragAndDropController
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
@@ -170,6 +171,7 @@
     private val desktopModeEventLogger: DesktopModeEventLogger,
     private val desktopModeUiEventLogger: DesktopModeUiEventLogger,
     private val desktopTilingDecorViewModel: DesktopTilingDecorViewModel,
+    private val desktopWallpaperActivityTokenProvider: DesktopWallpaperActivityTokenProvider,
 ) :
     RemoteCallable<DesktopTasksController>,
     Transitions.TransitionHandler,
@@ -881,6 +883,12 @@
             applyFreeformDisplayChange(wct, task, displayId)
         }
         wct.reparent(task.token, displayAreaInfo.token, true /* onTop */)
+        if (Flags.enableDisplayFocusInShellTransitions()) {
+            // Bring the destination display to top with includingParents=true, so that the
+            // destination display gains the display focus, which makes the top task in the display
+            // gains the global focus.
+            wct.reorder(task.token, /* onTop= */ true, /* includingParents= */ true)
+        }
 
         if (Flags.enablePerDisplayDesktopWallpaperActivity()) {
             performDesktopExitCleanupIfNeeded(task.taskId, task.displayId, wct)
@@ -1334,35 +1342,60 @@
 
     private fun addWallpaperActivity(displayId: Int, wct: WindowContainerTransaction) {
         logV("addWallpaperActivity")
-        val userHandle = UserHandle.of(userId)
-        val userContext = context.createContextAsUser(userHandle, /* flags= */ 0)
-        val intent = Intent(userContext, DesktopWallpaperActivity::class.java)
-        intent.putExtra(Intent.EXTRA_USER_HANDLE, userId)
-        val options =
-            ActivityOptions.makeBasic().apply {
-                launchWindowingMode = WINDOWING_MODE_FULLSCREEN
-                pendingIntentBackgroundActivityStartMode =
-                    ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
-                if (Flags.enableBugFixesForSecondaryDisplay()) {
-                    launchDisplayId = displayId
+        if (Flags.enableDesktopWallpaperActivityOnSystemUser()) {
+            val intent = Intent(context, DesktopWallpaperActivity::class.java)
+            val options =
+                ActivityOptions.makeBasic().apply {
+                    launchWindowingMode = WINDOWING_MODE_FULLSCREEN
+                    pendingIntentBackgroundActivityStartMode =
+                        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
+                    if (Flags.enableBugFixesForSecondaryDisplay()) {
+                        launchDisplayId = displayId
+                    }
                 }
-            }
-        val pendingIntent =
-            PendingIntent.getActivityAsUser(
-                userContext,
-                /* requestCode= */ 0,
-                intent,
-                PendingIntent.FLAG_IMMUTABLE,
-                /* options= */ null,
-                userHandle,
-            )
-        wct.sendPendingIntent(pendingIntent, intent, options.toBundle())
+            val pendingIntent =
+                PendingIntent.getActivity(
+                    context,
+                    /* requestCode = */ 0,
+                    intent,
+                    PendingIntent.FLAG_IMMUTABLE,
+                )
+            wct.sendPendingIntent(pendingIntent, intent, options.toBundle())
+        } else {
+            val userHandle = UserHandle.of(userId)
+            val userContext = context.createContextAsUser(userHandle, /* flags= */ 0)
+            val intent = Intent(userContext, DesktopWallpaperActivity::class.java)
+            intent.putExtra(Intent.EXTRA_USER_HANDLE, userId)
+            val options =
+                ActivityOptions.makeBasic().apply {
+                    launchWindowingMode = WINDOWING_MODE_FULLSCREEN
+                    pendingIntentBackgroundActivityStartMode =
+                        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
+                    if (Flags.enableBugFixesForSecondaryDisplay()) {
+                        launchDisplayId = displayId
+                    }
+                }
+            val pendingIntent =
+                PendingIntent.getActivityAsUser(
+                    userContext,
+                    /* requestCode= */ 0,
+                    intent,
+                    PendingIntent.FLAG_IMMUTABLE,
+                    /* options= */ null,
+                    userHandle,
+                )
+            wct.sendPendingIntent(pendingIntent, intent, options.toBundle())
+        }
     }
 
     private fun removeWallpaperActivity(wct: WindowContainerTransaction) {
-        taskRepository.wallpaperActivityToken?.let { token ->
+        desktopWallpaperActivityTokenProvider.getToken()?.let { token ->
             logV("removeWallpaperActivity")
-            wct.removeTask(token)
+            if (Flags.enableDesktopWallpaperActivityOnSystemUser()) {
+                wct.reorder(token, /* onTop= */ false)
+            } else {
+                wct.removeTask(token)
+            }
         }
     }
 
@@ -1390,9 +1423,7 @@
         desktopModeEnterExitTransitionListener?.onExitDesktopModeTransitionStarted(
             FULLSCREEN_ANIMATION_DURATION
         )
-        if (taskRepository.wallpaperActivityToken != null) {
-            removeWallpaperActivity(wct)
-        }
+        removeWallpaperActivity(wct)
     }
 
     fun releaseVisualIndicator() {
@@ -2577,8 +2608,7 @@
         val innerPrefix = "$prefix  "
         pw.println("${prefix}DesktopTasksController")
         DesktopModeStatus.dump(pw, innerPrefix, context)
-        pw.println("${prefix}userId=$userId")
-        taskRepository.dump(pw, innerPrefix)
+        userRepositories.dump(pw, innerPrefix)
     }
 
     /** The interface for calls from outside the shell, within the host process. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
index 45faba6..0330a5f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksLimiter.kt
@@ -127,14 +127,20 @@
 
         override fun onTransitionStarting(transition: IBinder) {
             val mActiveTaskDetails = activeTransitionTokensAndTasks[transition]
-            if (mActiveTaskDetails != null && mActiveTaskDetails.transitionInfo != null) {
-                // Begin minimize window CUJ instrumentation.
-                interactionJankMonitor.begin(
-                    mActiveTaskDetails.transitionInfo?.rootLeash,
-                    context,
-                    handler,
-                    CUJ_DESKTOP_MODE_MINIMIZE_WINDOW,
-                )
+            val info = mActiveTaskDetails?.transitionInfo ?: return
+            val minimizeChange = getMinimizeChange(info, mActiveTaskDetails.taskId) ?: return
+            // Begin minimize window CUJ instrumentation.
+            interactionJankMonitor.begin(
+                minimizeChange.leash,
+                context,
+                handler,
+                CUJ_DESKTOP_MODE_MINIMIZE_WINDOW,
+            )
+        }
+
+        private fun getMinimizeChange(info: TransitionInfo, taskId: Int): TransitionInfo.Change? {
+            return info.changes.find { change ->
+                change.taskInfo?.taskId == taskId && change.mode == TRANSIT_TO_BACK
             }
         }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
index 5c79658..e7a0077 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt
@@ -29,9 +29,11 @@
 import android.window.TransitionInfo
 import android.window.WindowContainerTransaction
 import com.android.internal.protolog.ProtoLog
+import com.android.window.flags.Flags
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.back.BackAnimationController
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.isExitDesktopModeTransition
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
 import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
 import com.android.wm.shell.shared.TransitionUtil
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
@@ -50,6 +52,7 @@
     private val shellTaskOrganizer: ShellTaskOrganizer,
     private val desktopMixedTransitionHandler: DesktopMixedTransitionHandler,
     private val backAnimationController: BackAnimationController,
+    private val desktopWallpaperActivityTokenProvider: DesktopWallpaperActivityTokenProvider,
     shellInit: ShellInit,
 ) : Transitions.TransitionObserver {
 
@@ -212,7 +215,7 @@
                 desktopRepository.getVisibleTaskCount(taskInfo.displayId) == 0 &&
                     change.mode == TRANSIT_CLOSE &&
                     taskInfo.windowingMode == WINDOWING_MODE_FREEFORM &&
-                    desktopRepository.wallpaperActivityToken != null
+                    desktopWallpaperActivityTokenProvider.getToken() != null
             ) {
                 transitionToCloseWallpaper = transition
                 currentProfileId = taskInfo.userId
@@ -232,13 +235,21 @@
         // TODO: b/332682201 Update repository state
         if (transitionToCloseWallpaper == transition) {
             // TODO: b/362469671 - Handle merging the animation when desktop is also closing.
-            val desktopRepository = desktopUserRepositories.getProfile(currentProfileId)
-            desktopRepository.wallpaperActivityToken?.let { wallpaperActivityToken ->
-                transitions.startTransition(
-                    TRANSIT_CLOSE,
-                    WindowContainerTransaction().removeTask(wallpaperActivityToken),
-                    null,
-                )
+            desktopWallpaperActivityTokenProvider.getToken()?.let { wallpaperActivityToken ->
+                if (Flags.enableDesktopWallpaperActivityOnSystemUser()) {
+                    transitions.startTransition(
+                        TRANSIT_TO_BACK,
+                        WindowContainerTransaction()
+                            .reorder(wallpaperActivityToken, /* onTop= */ false),
+                        null,
+                    )
+                } else {
+                    transitions.startTransition(
+                        TRANSIT_CLOSE,
+                        WindowContainerTransaction().removeTask(wallpaperActivityToken),
+                        null,
+                    )
+                }
             }
             transitionToCloseWallpaper = null
         }
@@ -251,10 +262,12 @@
         info.changes.forEach { change ->
             change.taskInfo?.let { taskInfo ->
                 if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) {
-                    val desktopRepository = desktopUserRepositories.getProfile(taskInfo.userId)
                     when (change.mode) {
                         WindowManager.TRANSIT_OPEN -> {
-                            desktopRepository.wallpaperActivityToken = taskInfo.token
+                            desktopWallpaperActivityTokenProvider.setToken(
+                                taskInfo.token,
+                                taskInfo.displayId,
+                            )
                             // After the task for the wallpaper is created, set it non-trimmable.
                             // This is important to prevent recents from trimming and removing the
                             // task.
@@ -263,7 +276,8 @@
                                     .setTaskTrimmableFromRecents(taskInfo.token, false)
                             )
                         }
-                        TRANSIT_CLOSE -> desktopRepository.wallpaperActivityToken = null
+                        TRANSIT_CLOSE ->
+                            desktopWallpaperActivityTokenProvider.removeToken(taskInfo.displayId)
                         else -> {}
                     }
                 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
index 8b5d1c5..7f3133e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopUserRepositories.kt
@@ -21,6 +21,7 @@
 import android.content.pm.UserInfo
 import android.os.UserManager
 import android.util.SparseArray
+import androidx.core.util.forEach
 import com.android.internal.protolog.ProtoLog
 import com.android.window.flags.Flags
 import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
@@ -31,6 +32,7 @@
 import com.android.wm.shell.sysui.ShellController
 import com.android.wm.shell.sysui.ShellInit
 import com.android.wm.shell.sysui.UserChangeListener
+import java.io.PrintWriter
 import kotlinx.coroutines.CoroutineScope
 
 /** Manages per-user DesktopRepository instances. */
@@ -87,6 +89,14 @@
         return desktopRepoByUserId.getOrCreate(profileId)
     }
 
+    /** Dumps [DesktopRepository] for each user. */
+    fun dump(pw: PrintWriter, prefix: String) {
+        desktopRepoByUserId.forEach { key, value ->
+            pw.println("${prefix}userId=$key")
+            value.dump(pw, prefix)
+        }
+    }
+
     override fun onUserChanged(newUserId: Int, userContext: Context) {
         logD("onUserChanged previousUserId=%d, newUserId=%d", userId, newUserId)
         userId = newUserId
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index d23c9d0..72c0642 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -37,6 +37,9 @@
 import com.android.internal.protolog.ProtoLog
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
 import com.android.wm.shell.animation.FloatProperties
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
 import com.android.wm.shell.protolog.ShellProtoLogGroup
 import com.android.wm.shell.shared.TransitionUtil
 import com.android.wm.shell.shared.animation.PhysicsAnimator
@@ -46,9 +49,6 @@
 import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition
 import com.android.wm.shell.splitscreen.SplitScreenController
 import com.android.wm.shell.transition.Transitions
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
 import com.android.wm.shell.transition.Transitions.TransitionHandler
 import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
 import com.android.wm.shell.windowdecor.MoveToDesktopAnimator.Companion.DRAG_FREEFORM_SCALE
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
index e683f62..a47e937 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/ToggleResizeDesktopTaskTransitionHandler.kt
@@ -30,8 +30,8 @@
 import androidx.core.animation.addListener
 import com.android.internal.jank.Cuj
 import com.android.internal.jank.InteractionJankMonitor
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE
 import com.android.wm.shell.transition.Transitions
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE
 import com.android.wm.shell.windowdecor.OnTaskResizeAnimationListener
 import java.util.function.Supplier
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/desktopwallpaperactivity/DesktopWallpaperActivityTokenProvider.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/desktopwallpaperactivity/DesktopWallpaperActivityTokenProvider.kt
new file mode 100644
index 0000000..a87004c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/desktopwallpaperactivity/DesktopWallpaperActivityTokenProvider.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.desktopmode.desktopwallpaperactivity
+
+import android.util.SparseArray
+import android.view.Display.DEFAULT_DISPLAY
+import android.window.WindowContainerToken
+
+/** Provides per display window container tokens for [DesktopWallpaperActivity]. */
+class DesktopWallpaperActivityTokenProvider {
+
+    private val wallpaperActivityTokenByDisplayId = SparseArray<WindowContainerToken>()
+
+    fun setToken(token: WindowContainerToken, displayId: Int = DEFAULT_DISPLAY) {
+        wallpaperActivityTokenByDisplayId[displayId] = token
+    }
+
+    fun getToken(displayId: Int = DEFAULT_DISPLAY): WindowContainerToken? {
+        return wallpaperActivityTokenByDisplayId[displayId]
+    }
+
+    fun removeToken(displayId: Int = DEFAULT_DISPLAY) {
+        wallpaperActivityTokenByDisplayId.delete(displayId)
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
index a611fe1..c4ff87d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
@@ -74,7 +74,7 @@
         mInitialDragData = data;
         mInitialDragFlags = dragFlags;
         displayLayout = dispLayout;
-        hideDragSourceTaskId = data.getDescription().getExtras() != null
+        hideDragSourceTaskId = data != null && data.getDescription().getExtras() != null
                 ? data.getDescription().getExtras().getInt(EXTRA_HIDE_DRAG_SOURCE_TASK_ID, -1)
                 : -1;
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
index fd387d1..3729653 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
@@ -350,7 +350,7 @@
         }
         cancelPhysicsAnimation();
         mMenuController.hideMenu(ANIM_TYPE_DISMISS, false /* resize */);
-        mPipScheduler.removePipAfterAnimation();
+        mPipScheduler.scheduleRemovePip();
     }
 
     /** Sets the movement bounds to use to constrain PIP position animations. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
index 4461a5c..7f673d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
@@ -122,34 +122,26 @@
      * Schedules exit PiP via expand transition.
      */
     public void scheduleExitPipViaExpand() {
-        WindowContainerTransaction wct = getExitPipViaExpandTransaction();
-        if (wct != null) {
-            mMainExecutor.execute(() -> {
+        mMainExecutor.execute(() -> {
+            if (!mPipTransitionState.isInPip()) return;
+            WindowContainerTransaction wct = getExitPipViaExpandTransaction();
+            if (wct != null) {
                 mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct,
                         null /* destinationBounds */);
-            });
-        }
-    }
-
-    // TODO: Optimize this by running the animation as part of the transition
-    /** Runs remove PiP animation and schedules remove PiP transition after the animation ends. */
-    public void removePipAfterAnimation() {
-        SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
-        PipAlphaAnimator animator = mPipAlphaAnimatorSupplier.get(mContext,
-                mPipTransitionState.getPinnedTaskLeash(), tx, PipAlphaAnimator.FADE_OUT);
-        animator.setAnimationEndCallback(this::scheduleRemovePipImmediately);
-        animator.start();
+            }
+        });
     }
 
     /** Schedules remove PiP transition. */
-    private void scheduleRemovePipImmediately() {
-        WindowContainerTransaction wct = getRemovePipTransaction();
-        if (wct != null) {
-            mMainExecutor.execute(() -> {
+    public void scheduleRemovePip() {
+        mMainExecutor.execute(() -> {
+            if (!mPipTransitionState.isInPip()) return;
+            WindowContainerTransaction wct = getRemovePipTransaction();
+            if (wct != null) {
                 mPipTransitionController.startExitTransition(TRANSIT_REMOVE_PIP, wct,
                         null /* destinationBounds */);
-            });
-        }
+            }
+        });
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index acb5622b..2e38449 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -278,7 +278,8 @@
         }
 
         if (isRemovePipTransition(info)) {
-            return removePipImmediately(info, startTransaction, finishTransaction, finishCallback);
+            mPipTransitionState.setState(PipTransitionState.EXITING_PIP);
+            return startRemoveAnimation(info, startTransaction, finishTransaction, finishCallback);
         }
         return false;
     }
@@ -668,13 +669,18 @@
         return true;
     }
 
-    private boolean removePipImmediately(@NonNull TransitionInfo info,
+    private boolean startRemoveAnimation(@NonNull TransitionInfo info,
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        startTransaction.apply();
-        finishCallback.onTransitionFinished(null);
-        mPipTransitionState.setState(PipTransitionState.EXITED_PIP);
+        TransitionInfo.Change pipChange = getChangeByToken(info,
+                mPipTransitionState.getPipTaskToken());
+        mFinishCallback = finishCallback;
+        PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipChange.getLeash(),
+                startTransaction, PipAlphaAnimator.FADE_OUT);
+        finishTransaction.setAlpha(pipChange.getLeash(), 0f);
+        animator.setAnimationEndCallback(this::finishTransition);
+        animator.start();
         return true;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 246760e..535112f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -746,6 +746,7 @@
             ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Reordering hide-task to bottom");
             wct.reorder(hideTaskToken, false /* onTop */);
         }
+        prepareTasksForSplitScreen(new int[] {taskId}, wct);
         wct.startTask(taskId, options);
         // If this should be mixed, send the task to avoid split handle transition directly.
         if (mMixedHandler != null && mMixedHandler.isTaskInPip(taskId, mTaskOrganizer)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 2747249..0519a5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -89,8 +89,6 @@
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
                 "create taskSnapshot surface for task: %d", taskId);
 
-        final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
-
         final WindowManager.LayoutParams layoutParams = SnapshotDrawerUtils.createLayoutParameters(
                 info, TITLE_FORMAT + taskId, TYPE_APPLICATION_STARTING,
                 snapshot.getHardwareBuffer().getFormat(), appToken);
@@ -152,8 +150,8 @@
             return null;
         }
 
-        SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
-                info.taskBounds, topWindowInsetsState, true /* releaseAfterDraw */);
+        SnapshotDrawerUtils.drawSnapshotOnSurface(layoutParams, surfaceControl, snapshot,
+                info.taskBounds, true /* releaseAfterDraw */);
         snapshotSurface.mHasDrawn = true;
         snapshotSurface.reportDrawn();
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
index 2a22d4d..34d1011 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
@@ -26,7 +26,6 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
 import android.view.Display;
-import android.view.InsetsState;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
 import android.view.WindowManager;
@@ -77,12 +76,11 @@
         final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
                 mContext, display, wlw, "WindowlessSnapshotWindowCreator");
         final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
-        final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
         final FrameLayout rootLayout = new FrameLayout(
                 mSplashscreenContentDrawer.createViewContextWrapper(mContext));
         mViewHost.setView(rootLayout, lp);
-        SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
-                windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
+        SnapshotDrawerUtils.drawSnapshotOnSurface(lp, wlw.mChildSurface, snapshot,
+                windowBounds, false /* releaseAfterDraw */);
 
         final ActivityManager.TaskDescription taskDescription =
                 SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
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
index 1c7e62b..b5220c4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -20,7 +20,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
 
-import static com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
+import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
 import static com.android.wm.shell.transition.Transitions.TransitionObserver;
 
 import android.annotation.NonNull;
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 a7d6301..df81821 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
@@ -85,6 +85,7 @@
 import com.android.wm.shell.common.ExternalInterfaceBinder;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes;
 import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.shared.FocusTransitionListener;
@@ -167,22 +168,6 @@
     /** Transition type for maximize to freeform transition. */
     public static final int TRANSIT_RESTORE_FROM_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 9;
 
-    /** Transition type for starting the drag to desktop mode. */
-    public static final int TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP =
-            WindowManager.TRANSIT_FIRST_CUSTOM + 10;
-
-    /** Transition type for finalizing the drag to desktop mode. */
-    public static final int TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP =
-            WindowManager.TRANSIT_FIRST_CUSTOM + 11;
-
-    /** Transition type to cancel the drag to desktop mode. */
-    public static final int TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP =
-            WindowManager.TRANSIT_FIRST_CUSTOM + 13;
-
-    /** Transition type to animate the toggle resize between the max and default desktop sizes. */
-    public static final int TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE =
-            WindowManager.TRANSIT_FIRST_CUSTOM + 14;
-
     /** Transition to resize PiP task. */
     public static final int TRANSIT_RESIZE_PIP = TRANSIT_FIRST_CUSTOM + 16;
 
@@ -1872,11 +1857,6 @@
             case TRANSIT_SPLIT_DISMISS -> "SPLIT_DISMISS";
             case TRANSIT_MAXIMIZE -> "MAXIMIZE";
             case TRANSIT_RESTORE_FROM_MAXIMIZE -> "RESTORE_FROM_MAXIMIZE";
-            case TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP -> "DESKTOP_MODE_START_DRAG_TO_DESKTOP";
-            case TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP -> "DESKTOP_MODE_END_DRAG_TO_DESKTOP";
-            case TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP ->
-                    "DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP";
-            case TRANSIT_DESKTOP_MODE_TOGGLE_RESIZE -> "DESKTOP_MODE_TOGGLE_RESIZE";
             case TRANSIT_RESIZE_PIP -> "RESIZE_PIP";
             case TRANSIT_TASK_FRAGMENT_DRAG_RESIZE -> "TASK_FRAGMENT_DRAG_RESIZE";
             case TRANSIT_SPLIT_PASSTHROUGH -> "SPLIT_PASSTHROUGH";
@@ -1886,6 +1866,9 @@
             case TRANSIT_END_RECENTS_TRANSITION -> "END_RECENTS_TRANSITION";
             default -> "";
         };
+        if (typeStr.isEmpty()) {
+            typeStr = DesktopModeTransitionTypes.transitTypeToString(transitType);
+        }
         return typeStr + "(FIRST_CUSTOM+" + (transitType - TRANSIT_FIRST_CUSTOM) + ")";
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java
new file mode 100644
index 0000000..0d75e65
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.windowdecor;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.shared.FocusTransitionListener;
+import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
+import com.android.wm.shell.shared.annotations.ShellMainThread;
+import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.FocusTransitionObserver;
+import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
+import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
+
+/**
+ * Works with decorations that extend {@link CarWindowDecoration}.
+ */
+public abstract class CarWindowDecorViewModel
+        implements WindowDecorViewModel, FocusTransitionListener {
+    private static final String TAG = "CarWindowDecorViewModel";
+
+    private final ShellTaskOrganizer mTaskOrganizer;
+    private final Context mContext;
+    private final @ShellBackgroundThread ShellExecutor mBgExecutor;
+    private final ShellExecutor mMainExecutor;
+    private final DisplayController mDisplayController;
+    private final FocusTransitionObserver mFocusTransitionObserver;
+    private final SyncTransactionQueue mSyncQueue;
+    private final SparseArray<CarWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
+    private final WindowDecorViewHostSupplier<WindowDecorViewHost> mWindowDecorViewHostSupplier;
+
+    public CarWindowDecorViewModel(
+            Context context,
+            @ShellBackgroundThread ShellExecutor bgExecutor,
+            @ShellMainThread ShellExecutor shellExecutor,
+            ShellInit shellInit,
+            ShellTaskOrganizer taskOrganizer,
+            DisplayController displayController,
+            SyncTransactionQueue syncQueue,
+            FocusTransitionObserver focusTransitionObserver,
+            WindowDecorViewHostSupplier<WindowDecorViewHost> windowDecorViewHostSupplier) {
+        mContext = context;
+        mMainExecutor = shellExecutor;
+        mBgExecutor = bgExecutor;
+        mTaskOrganizer = taskOrganizer;
+        mDisplayController = displayController;
+        mFocusTransitionObserver = focusTransitionObserver;
+        mSyncQueue = syncQueue;
+        mWindowDecorViewHostSupplier = windowDecorViewHostSupplier;
+
+        shellInit.addInitCallback(this::onInit, this);
+    }
+
+    private void onInit() {
+        mFocusTransitionObserver.setLocalFocusTransitionListener(this, mMainExecutor);
+    }
+
+    @Override
+    public void onFocusedTaskChanged(int taskId, boolean isFocusedOnDisplay,
+            boolean isFocusedGlobally) {
+        // no-op
+    }
+
+    @Override
+    public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
+        // no-op
+    }
+
+    @Override
+    public void setSplitScreenController(SplitScreenController splitScreenController) {
+        // no-op
+    }
+
+    @Override
+    public boolean onTaskOpening(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        if (!shouldShowWindowDecor(taskInfo)) {
+            return false;
+        }
+        createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+        return true;
+    }
+
+    @Override
+    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+        if (decoration == null) {
+            return;
+        }
+
+        if (!shouldShowWindowDecor(taskInfo)) {
+            destroyWindowDecoration(taskInfo);
+            return;
+        }
+
+        decoration.relayout(taskInfo, decoration.mHasGlobalFocus, decoration.mExclusionRegion);
+    }
+
+    @Override
+    public void onTaskVanished(RunningTaskInfo taskInfo) {
+        // A task vanishing doesn't necessarily mean the task was closed, it could also mean its
+        // windowing mode changed. We're only interested in closing tasks so checking whether
+        // its info still exists in the task organizer is one way to disambiguate.
+        final boolean closed = mTaskOrganizer.getRunningTaskInfo(taskInfo.taskId) == null;
+        if (closed) {
+            // Destroying the window decoration is usually handled when a TRANSIT_CLOSE transition
+            // changes happen, but there are certain cases in which closing tasks aren't included
+            // in transitions, such as when a non-visible task is closed. See b/296921167.
+            // Destroy the decoration here in case the lack of transition missed it.
+            destroyWindowDecoration(taskInfo);
+        }
+    }
+
+    @Override
+    public void onTaskChanging(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+        if (!shouldShowWindowDecor(taskInfo)) {
+            if (decoration != null) {
+                destroyWindowDecoration(taskInfo);
+            }
+            return;
+        }
+
+        if (decoration == null) {
+            createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+        } else {
+            decoration.relayout(taskInfo, startT, finishT);
+        }
+    }
+
+    @Override
+    public void onTaskClosing(
+            RunningTaskInfo taskInfo,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+        if (decoration == null) {
+            return;
+        }
+        decoration.relayout(taskInfo, startT, finishT);
+    }
+
+    @Override
+    public void destroyWindowDecoration(RunningTaskInfo taskInfo) {
+        final CarWindowDecoration decoration =
+                mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId);
+        if (decoration == null) {
+            return;
+        }
+
+        decoration.close();
+    }
+
+    /**
+     * @return {@code true} if the task/activity associated with {@code taskInfo} should show
+     * window decoration.
+     */
+    protected abstract boolean shouldShowWindowDecor(RunningTaskInfo taskInfo);
+
+    private void createWindowDecoration(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+        if (oldDecoration != null) {
+            // close the old decoration if it exists to avoid two window decorations being added
+            oldDecoration.close();
+        }
+        final CarWindowDecoration windowDecoration =
+                new CarWindowDecoration(
+                        mContext,
+                        mContext.createContextAsUser(UserHandle.of(taskInfo.userId), 0 /* flags */),
+                        mDisplayController,
+                        mTaskOrganizer,
+                        taskInfo,
+                        taskSurface,
+                        mBgExecutor,
+                        mWindowDecorViewHostSupplier,
+                        new ButtonClickListener(taskInfo));
+        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
+        windowDecoration.relayout(taskInfo, startT, finishT);
+    }
+
+    private class ButtonClickListener implements View.OnClickListener {
+        private final WindowContainerToken mTaskToken;
+        private final int mDisplayId;
+
+        private ButtonClickListener(RunningTaskInfo taskInfo) {
+            mTaskToken = taskInfo.token;
+            mDisplayId = taskInfo.displayId;
+        }
+
+        @Override
+        public void onClick(View v) {
+            final int id = v.getId();
+            if (id == R.id.close_window) {
+                WindowContainerTransaction wct = new WindowContainerTransaction();
+                wct.removeTask(mTaskToken);
+                mSyncQueue.queue(wct);
+            } else if (id == R.id.back_button) {
+                sendBackEvent(KeyEvent.ACTION_DOWN, mDisplayId);
+                sendBackEvent(KeyEvent.ACTION_UP, mDisplayId);
+            }
+        }
+
+        private void sendBackEvent(int action, int displayId) {
+            final long when = SystemClock.uptimeMillis();
+            final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK,
+                    0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD,
+                    0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+                    InputDevice.SOURCE_KEYBOARD);
+
+            ev.setDisplayId(displayId);
+            if (!mContext.getSystemService(InputManager.class)
+                    .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
+                Log.e(TAG, "Inject input event fail");
+            }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
new file mode 100644
index 0000000..1ca82d2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.wm.shell.windowdecor;
+
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.view.InsetsState;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
+import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
+import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
+
+/**
+ * {@link WindowDecoration} to show app controls for windows on automotive.
+ */
+public class CarWindowDecoration extends WindowDecoration<WindowDecorLinearLayout> {
+    private WindowDecorLinearLayout mRootView;
+    private @ShellBackgroundThread final ShellExecutor mBgExecutor;
+    private final View.OnClickListener mClickListener;
+
+    CarWindowDecoration(
+            Context context,
+            @android.annotation.NonNull Context userContext,
+            DisplayController displayController,
+            ShellTaskOrganizer taskOrganizer,
+            ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            @ShellBackgroundThread ShellExecutor bgExecutor,
+            WindowDecorViewHostSupplier<WindowDecorViewHost> windowDecorViewHostSupplier,
+            View.OnClickListener clickListener) {
+        super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
+                windowDecorViewHostSupplier);
+        mBgExecutor = bgExecutor;
+        mClickListener = clickListener;
+    }
+
+    @Override
+    void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus,
+            @NonNull Region displayExclusionRegion) {
+        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        relayout(taskInfo, t, t);
+    }
+
+    @SuppressLint("MissingPermission")
+    void relayout(ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+
+        RelayoutParams relayoutParams = new RelayoutParams();
+        RelayoutResult<WindowDecorLinearLayout> outResult = new RelayoutResult<>();
+
+        updateRelayoutParams(relayoutParams, taskInfo,
+                mDisplayController.getInsetsState(taskInfo.displayId));
+
+        relayout(relayoutParams, startT, finishT, wct, mRootView, outResult);
+        // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
+        mBgExecutor.execute(() -> mTaskOrganizer.applyTransaction(wct));
+
+        if (outResult.mRootView == null) {
+            // This means something blocks the window decor from showing, e.g. the task is hidden.
+            // Nothing is set up in this case including the decoration surface.
+            return;
+        }
+        if (mRootView != outResult.mRootView) {
+            mRootView = outResult.mRootView;
+            setupRootView(outResult.mRootView, mClickListener);
+        }
+    }
+
+    @Override
+    @NonNull
+    Rect calculateValidDragArea() {
+        return new Rect();
+    }
+
+    @Override
+    int getCaptionViewId() {
+        return R.id.caption;
+    }
+
+    private void updateRelayoutParams(
+            RelayoutParams relayoutParams,
+            ActivityManager.RunningTaskInfo taskInfo,
+            InsetsState displayInsetsState) {
+        relayoutParams.reset();
+        relayoutParams.mRunningTaskInfo = taskInfo;
+        // todo(b/382071404): update to car specific UI
+        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
+        relayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
+        relayoutParams.mIsCaptionVisible = mIsStatusBarVisible && !mIsKeyguardVisibleAndOccluded;
+        relayoutParams.mCaptionTopPadding = 0;
+        relayoutParams.mInsetSourceFlags |= FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR;
+        relayoutParams.mApplyStartTransactionOnDraw = true;
+    }
+
+    /**
+     * Sets up listeners when a new root view is created.
+     */
+    private void setupRootView(View rootView, View.OnClickListener onClickListener) {
+        final View caption = rootView.findViewById(R.id.caption);
+        final View close = caption.findViewById(R.id.close_window);
+        if (close != null) {
+            close.setOnClickListener(onClickListener);
+        }
+        final View back = caption.findViewById(R.id.back_button);
+        if (back != null) {
+            back.setOnClickListener(onClickListener);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 7928e5e..a7a5f09 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -935,10 +935,12 @@
                 //  back to the decoration using
                 //  {@link DesktopModeWindowDecoration#setOnMaximizeOrRestoreClickListener}, which
                 //  should shared with the maximize menu's maximize/restore actions.
+                final DesktopRepository desktopRepository = mDesktopUserRepositories.getProfile(
+                        decoration.mTaskInfo.userId);
                 if (Flags.enableFullyImmersiveInDesktop()
-                        && TaskInfoKt.getRequestingImmersive(decoration.mTaskInfo)) {
-                    // Task is requesting immersive, so it should either enter or exit immersive,
-                    // depending on immersive state.
+                        && desktopRepository.isTaskInFullImmersiveState(
+                                decoration.mTaskInfo.taskId)) {
+                    // Task is in immersive and should exit.
                     onEnterOrExitImmersive(decoration.mTaskInfo);
                 } else {
                     // Full immersive is disabled or task doesn't request/support it, so just
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index 9972247..ab1ac1a 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -44,6 +44,7 @@
 import android.tools.flicker.assertors.assertions.AppWindowRemainInsideDisplayBounds
 import android.tools.flicker.assertors.assertions.AppWindowReturnsToStartBoundsAndPosition
 import android.tools.flicker.assertors.assertions.LauncherWindowReplacesAppAsTopWindow
+import android.tools.flicker.assertors.assertions.VisibleLayersShownMoreThanOneConsecutiveEntry
 import android.tools.flicker.config.AssertionTemplates
 import android.tools.flicker.config.FlickerConfigEntry
 import android.tools.flicker.config.ScenarioId
@@ -463,7 +464,9 @@
                     }
                 ),
                 assertions =
-                AssertionTemplates.COMMON_ASSERTIONS +
+                    AssertionTemplates.COMMON_ASSERTIONS.toMutableMap().also {
+                        it.remove(VisibleLayersShownMoreThanOneConsecutiveEntry())
+                    } +
                     listOf(
                         AppWindowOnTopAtStart(DESKTOP_MODE_APP),
                         AppWindowBecomesInvisible(DESKTOP_MODE_APP),
@@ -489,7 +492,9 @@
                     }
                 ),
                 assertions =
-                AssertionTemplates.COMMON_ASSERTIONS +
+                    AssertionTemplates.COMMON_ASSERTIONS.toMutableMap().also {
+                        it.remove(VisibleLayersShownMoreThanOneConsecutiveEntry())
+                    } +
                     listOf(
                         AppWindowOnTopAtStart(DESKTOP_MODE_APP),
                         AppWindowBecomesInvisible(DESKTOP_MODE_APP),
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MaximizeAppWithKeyboard.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MaximizeAppWithKeyboard.kt
new file mode 100644
index 0000000..b399e9b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MaximizeAppWithKeyboard.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.tools.Rotation.ROTATION_90
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.MAXIMIZE_APP
+import com.android.wm.shell.scenarios.MaximizeAppWindow
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Maximize app window by pressing META + = on the keyboard.
+ *
+ * Assert that the app window keeps the same increases in size, filling the vertical and horizontal
+ * stable display bounds.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class MaximizeAppWithKeyboard : MaximizeAppWindow(rotation = ROTATION_90, usingKeyboard = true) {
+    @ExpectedScenarios(["MAXIMIZE_APP"])
+    @Test
+    override fun maximizeAppWindow() = super.maximizeAppWindow()
+
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(MAXIMIZE_APP)
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAppsWithKeyboard.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAppsWithKeyboard.kt
new file mode 100644
index 0000000..56f1dcb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/MinimizeAppsWithKeyboard.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.MINIMIZE_APP
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.MINIMIZE_LAST_APP
+import com.android.wm.shell.scenarios.MinimizeAppWindows
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Minimize app windows by pressing META + -.
+ *
+ * Assert that the app windows gets hidden.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class MinimizeAppsWithKeyboard : MinimizeAppWindows(usingKeyboard = true) {
+    @ExpectedScenarios(["MINIMIZE_APP", "MINIMIZE_LAST_APP"])
+    @Test
+    override fun minimizeAllAppWindows() = super.minimizeAllAppWindows()
+
+    companion object {
+        @JvmStatic
+        @FlickerConfigProvider
+        fun flickerConfigProvider(): FlickerConfig =
+            FlickerConfig()
+                .use(FlickerServiceConfig.DEFAULT)
+                .use(MINIMIZE_APP)
+                .use(MINIMIZE_LAST_APP)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfLiveOverviewTaskTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfLiveOverviewTaskTest.kt
new file mode 100644
index 0000000..e28f0c0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfLiveOverviewTaskTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.EnterDesktopViaMenuOfLiveOverviewTask
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [EnterDesktopViaMenuOfLiveOverviewTask]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class EnterDesktopViaMenuOfLiveOverviewTaskTest : EnterDesktopViaMenuOfLiveOverviewTask()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfStaticOverviewTaskTest.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfStaticOverviewTaskTest.kt
new file mode 100644
index 0000000..fac749b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/functional/EnterDesktopViaMenuOfStaticOverviewTaskTest.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.functional
+
+import android.platform.test.annotations.Postsubmit
+import com.android.wm.shell.scenarios.EnterDesktopViaMenuOfStaticOverviewTask
+import org.junit.runner.RunWith
+import org.junit.runners.BlockJUnit4ClassRunner
+
+/* Functional test for [EnterDesktopViaMenuOfStaticOverviewTask]. */
+@RunWith(BlockJUnit4ClassRunner::class)
+@Postsubmit
+class EnterDesktopViaMenuOfStaticOverviewTaskTest : EnterDesktopViaMenuOfStaticOverviewTask()
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfLiveOverviewTask.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfLiveOverviewTask.kt
new file mode 100644
index 0000000..43a2ae3
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfLiveOverviewTask.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+@Ignore("Base Test Class")
+abstract class EnterDesktopViaMenuOfLiveOverviewTask
+constructor() {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val mailApp = MailAppHelper(instrumentation)
+
+    @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        // Clear all tasks
+        val overview = tapl.goHome().switchToOverview()
+        if (overview.hasTasks()) {
+            overview.dismissAllTasks()
+        }
+        mailApp.open()
+    }
+
+    @Test
+    open fun desktopViaMenuOfLiveOverviewTask() {
+        tapl.getLaunchedAppState().switchToOverview()
+            .getCurrentTask().tapMenu().tapDesktopMenuItem()
+    }
+
+    @After
+    fun teardown() {
+        mailApp.exit(wmHelper)
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfStaticOverviewTask.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfStaticOverviewTask.kt
new file mode 100644
index 0000000..57647d6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/EnterDesktopViaMenuOfStaticOverviewTask.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+@Ignore("Base Test Class")
+abstract class EnterDesktopViaMenuOfStaticOverviewTask constructor() {
+
+    private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+    private val tapl = LauncherInstrumentation()
+    private val wmHelper = WindowManagerStateHelper(instrumentation)
+    private val device = UiDevice.getInstance(instrumentation)
+    private val mailApp = MailAppHelper(instrumentation)
+
+    @Rule
+    @JvmField
+    val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, Rotation.ROTATION_0)
+
+    @Before
+    fun setup() {
+        Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        // Clear all tasks
+        val overview = tapl.goHome().switchToOverview()
+        if (overview.hasTasks()) {
+            overview.dismissAllTasks()
+        }
+        mailApp.open()
+        tapl.goHome().switchToOverview()
+    }
+
+    @Test
+    open fun desktopViaMenuOfStaticOverviewTask() {
+        tapl.overview.getCurrentTask().tapMenu().tapDesktopMenuItem()
+    }
+
+    @After
+    fun teardown() {
+        mailApp.exit()
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
index d2be494..966aea3 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MaximizeAppWindow.kt
@@ -38,8 +38,11 @@
 
 @Ignore("Test Base Class")
 abstract class MaximizeAppWindow
-constructor(private val rotation: Rotation = Rotation.ROTATION_0, isResizable: Boolean = true) {
-
+constructor(
+    private val rotation: Rotation = Rotation.ROTATION_0,
+    isResizable: Boolean = true,
+    private val usingKeyboard: Boolean = false
+) {
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     private val tapl = LauncherInstrumentation()
     private val wmHelper = WindowManagerStateHelper(instrumentation)
@@ -55,6 +58,9 @@
     @Before
     fun setup() {
         Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
+        if (usingKeyboard) {
+            Assume.assumeTrue(Flags.enableTaskResizingKeyboardShortcuts())
+        }
         tapl.setEnableRotation(true)
         tapl.setExpectedRotation(rotation.value)
         ChangeDisplayOrientationRule.setRotation(rotation)
@@ -63,7 +69,7 @@
 
     @Test
     open fun maximizeAppWindow() {
-        testApp.maximiseDesktopApp(wmHelper, device)
+        testApp.maximiseDesktopApp(wmHelper, device, usingKeyboard = usingKeyboard)
     }
 
     @After
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MinimizeAppWindows.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MinimizeAppWindows.kt
index 971637b..46c97b0 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MinimizeAppWindows.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/MinimizeAppWindows.kt
@@ -43,7 +43,10 @@
  */
 @Ignore("Test Base Class")
 abstract class MinimizeAppWindows
-constructor(private val rotation: Rotation = Rotation.ROTATION_0) {
+constructor(
+    private val rotation: Rotation = Rotation.ROTATION_0,
+    private val usingKeyboard: Boolean = false
+) {
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     private val tapl = LauncherInstrumentation()
     private val wmHelper = WindowManagerStateHelper(instrumentation)
@@ -58,6 +61,9 @@
     fun setup() {
         Assume.assumeTrue(Flags.enableDesktopWindowingMode() && tapl.isTablet)
         Assume.assumeTrue(Flags.enableMinimizeButton())
+        if (usingKeyboard) {
+            Assume.assumeTrue(Flags.enableTaskResizingKeyboardShortcuts())
+        }
         tapl.setEnableRotation(true)
         tapl.setExpectedRotation(rotation.value)
         ChangeDisplayOrientationRule.setRotation(rotation)
@@ -68,9 +74,9 @@
 
     @Test
     open fun minimizeAllAppWindows() {
-        testApp3.minimizeDesktopApp(wmHelper, device)
-        testApp2.minimizeDesktopApp(wmHelper, device)
-        testApp1.minimizeDesktopApp(wmHelper, device)
+        testApp3.minimizeDesktopApp(wmHelper, device, usingKeyboard = usingKeyboard)
+        testApp2.minimizeDesktopApp(wmHelper, device, usingKeyboard = usingKeyboard)
+        testApp1.minimizeDesktopApp(wmHelper, device, usingKeyboard = usingKeyboard)
     }
 
     @After
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp
index f40edae..6e0dcdb 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp
@@ -115,6 +115,11 @@
         "com.android.wm.shell.flicker.pip.PipPinchInTest",
         "com.android.wm.shell.flicker.pip.SetRequestedOrientationWhilePinned",
         "com.android.wm.shell.flicker.pip.ShowPipAndRotateDisplay",
+        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfAutoEnterPipOnGoToHomeTest",
+        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipOnUserLeaveHintTest",
+        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipViaAppUiButtonTest",
+        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaExpandButtonTest",
+        "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaIntentTest",
     ],
     test_suites: ["device-tests"],
 }
@@ -266,12 +271,7 @@
     test_suites: ["device-tests"],
 }
 
-test_module_config {
-    name: "WMShellFlickerTestsPip-nonMatchParent",
-    base: "WMShellFlickerTestsPip",
-    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.*"],
-    test_suites: ["device-tests"],
-}
+// Not-match Parent test cases
 
 test_module_config {
     name: "WMShellFlickerTestsPip-BottomHalfExitPipToAppViaExpandButtonTest",
@@ -287,5 +287,26 @@
     test_suites: ["device-tests"],
 }
 
+test_module_config {
+    name: "WMShellFlickerTestsPip-BottomHalfAutoEnterPipOnGoToHomeTest",
+    base: "WMShellFlickerTestsPip",
+    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfAutoEnterPipOnGoToHomeTest"],
+    test_suites: ["device-tests"],
+}
+
+test_module_config {
+    name: "WMShellFlickerTestsPip-BottomHalfEnterPipOnUserLeaveHintTest",
+    base: "WMShellFlickerTestsPip",
+    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipOnUserLeaveHintTest"],
+    test_suites: ["device-tests"],
+}
+
+test_module_config {
+    name: "WMShellFlickerTestsPip-BottomHalfEnterPipViaAppUiButtonTest",
+    base: "WMShellFlickerTestsPip",
+    include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipViaAppUiButtonTest"],
+    test_suites: ["device-tests"],
+}
+
 // End breakdowns for WMShellFlickerTestsPip module
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index 609a284..84d53d5 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -24,20 +24,16 @@
 import android.tools.flicker.junit.FlickerParametersRunnerFactory
 import android.tools.flicker.legacy.FlickerBuilder
 import android.tools.flicker.legacy.LegacyFlickerTest
-import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder
-import android.tools.flicker.subject.exceptions.IncorrectRegionException
-import android.tools.flicker.subject.layers.LayerSubject
 import com.android.server.wm.flicker.helpers.PipAppHelper
 import com.android.wm.shell.Flags
 import com.android.wm.shell.flicker.pip.common.EnterPipTransition
+import com.android.wm.shell.flicker.pip.common.widthNotSmallerThan
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
-import kotlin.math.abs
-
 
 /**
  * Test entering pip from an app via auto-enter property when navigating to home.
@@ -77,22 +73,6 @@
         }
     }
 
-    override val defaultTeardown: FlickerBuilder.() -> Unit = { teardown { pipApp.exit(wmHelper) } }
-
-    private val widthNotSmallerThan: LayerSubject.(LayerSubject) -> Unit = {
-        val width = visibleRegion.region.bounds.width()
-        val otherWidth = it.visibleRegion.region.bounds.width()
-        if (width < otherWidth && abs(width - otherWidth) > EPSILON) {
-            val errorMsgBuilder =
-                ExceptionMessageBuilder()
-                    .forSubject(this)
-                    .forIncorrectRegion("width. $width smaller than $otherWidth")
-                    .setExpected(width)
-                    .setActual(otherWidth)
-            throw IncorrectRegionException(errorMsgBuilder)
-        }
-    }
-
     @Postsubmit
     @Test
     override fun pipLayerReduces() {
@@ -161,9 +141,4 @@
     override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
         super.visibleLayersShownMoreThanOneConsecutiveEntry()
     }
-
-    companion object {
-        // TODO(b/363080056): A margin of error allowed on certain layer size calculations.
-        const val EPSILON = 1
-    }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 4399a23..38f37b4 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -88,6 +88,7 @@
         super.pipOverlayLayerAppearThenDisappear()
     }
 
+    // TODO(b/385086051): check if we can remove optional = true in the test.
     @Presubmit
     @Test
     fun pipAppWindowVisibleChanges() {
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipUtils.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipUtils.kt
new file mode 100644
index 0000000..3b98d9b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/common/PipUtils.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip.common
+
+import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder
+import android.tools.flicker.subject.exceptions.IncorrectRegionException
+import android.tools.flicker.subject.layers.LayerSubject
+import kotlin.math.abs
+
+// TODO(b/363080056): A margin of error allowed on certain layer size calculations.
+const val EPSILON = 1
+
+internal val widthNotSmallerThan: LayerSubject.(LayerSubject) -> Unit = {
+    val width = visibleRegion.region.bounds.width()
+    val otherWidth = it.visibleRegion.region.bounds.width()
+    if (width < otherWidth && abs(width - otherWidth) > EPSILON) {
+        val errorMsgBuilder =
+            ExceptionMessageBuilder()
+                .forSubject(this)
+                .forIncorrectRegion("width. $width smaller than $otherWidth")
+                .setExpected(width)
+                .setActual(otherWidth)
+        throw IncorrectRegionException(errorMsgBuilder)
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfAutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfAutoEnterPipOnGoToHomeTest.kt
new file mode 100644
index 0000000..89f0226
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfAutoEnterPipOnGoToHomeTest.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip.nonmatchparent
+
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
+import android.platform.test.annotations.RequiresDevice
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import androidx.test.filters.FlakyTest
+import com.android.window.flags.Flags
+import com.android.wm.shell.flicker.pip.common.widthNotSmallerThan
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app with non-match parent layout via auto-enter property when
+ * navigating to home.
+ *
+ * To run this test: `atest WMShellFlickerTestsPip:BottomHalfAutoEnterPipOnGoToHomeTest`
+ *
+ * Actions:
+ * ```
+ *     Launch [BottomHalfPipLaunchingActivity] in full screen
+ *     Launch [BottomHalfPipActivity] with bottom half layout
+ *     Select "Auto-enter PiP" radio button
+ *     Press Home button or swipe up to go Home and put [BottomHalfPipActivity] in pip mode
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. All assertions are inherited from [EnterPipTest]
+ *     2. Part of the test setup occurs automatically via
+ *        [android.tools.flicker.legacy.runner.TransitionRunner],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2.
+@RequiresFlagsDisabled(com.android.wm.shell.Flags.FLAG_ENABLE_PIP2)
+@RequiresFlagsEnabled(Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY)
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class BottomHalfAutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) :
+    BottomHalfEnterPipTransition(flicker) {
+
+    override val thisTransition: FlickerBuilder.() -> Unit = { transitions {
+        tapl.goHome()
+        pipApp.waitForPip(wmHelper)
+    } }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntent(wmHelper)
+            pipApp.enableAutoEnterForPipActivity()
+        }
+    }
+
+    @FlakyTest(bugId = 289943985)
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    /* Gestural Navigation */
+
+    /**
+     * Checks that [pipApp] window's width is first decreasing then increasing.
+     *
+     * In gestural navigation mode, auto entering PiP can initially make the layer smaller before it
+     * gets larger.
+     * This tests verifies the width of the PiP layer first decreases and then increases due to
+     * size and scale animations going to different directions.
+     *
+     * Note that we still allow a margin of error of 1px, since around the time
+     * of handoff between gesture nav task view simulator and
+     * SwipePipToHomeAnimator, crop can get a bit smaller and scale can get a
+     * bit larger if swiped aggressively - this can produce off-by-1 errors for
+     * width too.
+     */
+    @Postsubmit
+    @Test
+    fun pipLayerWidthDecreasesThenIncreases() {
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        flicker.assertLayers {
+            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+            var previousLayer = pipLayerList[0]
+            var currentLayer = previousLayer
+            var i = 0
+            invoke("layer area is decreasing") {
+                if (i < pipLayerList.size - 1) {
+                    previousLayer = currentLayer
+                    currentLayer = pipLayerList[++i]
+                    previousLayer.widthNotSmallerThan(currentLayer)
+                }
+            }.then().invoke("layer are is increasing", true /* isOptional */) {
+                if (i < pipLayerList.size - 1) {
+                    previousLayer = currentLayer
+                    currentLayer = pipLayerList[++i]
+                    currentLayer.widthNotSmallerThan(previousLayer)
+                }
+            }
+        }
+    }
+
+    /* 3-button Navigation */
+
+    /**
+     * The PIP layer reduces continuously in 3-Button navigation mode.
+     */
+    @Postsubmit
+    @Test
+    override fun pipLayerReduces() {
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        flicker.assertLayers {
+            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+            pipLayerList.zipWithNext { previous, current ->
+                current.visibleRegion.notBiggerThan(previous.visibleRegion.region)
+            }
+        }
+    }
+
+    /** Checks that [pipApp] window is animated towards default position in right bottom corner */
+    @FlakyTest(bugId = 255578530)
+    @Test
+    fun pipLayerMovesTowardsRightBottomCorner() {
+        // in gestural nav the swipe makes PiP first go upwards
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        flicker.assertLayers {
+            val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+            // Pip animates towards the right bottom corner, but because it is being resized at the
+            // same time, it is possible it shrinks first quickly below the default position and get
+            // moved up after that in just few last frames
+            pipLayerList.zipWithNext { previous, current ->
+                current.visibleRegion.isToTheRightBottom(previous.visibleRegion.region, 3)
+            }
+        }
+    }
+
+    @Presubmit
+    @Test
+    override fun focusChanges() {
+        // in gestural nav the focus goes to different activity on swipe up
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.focusChanges()
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipOnUserLeaveHintTest.kt
new file mode 100644
index 0000000..8642b6c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipOnUserLeaveHintTest.kt
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip.nonmatchparent
+
+import android.platform.test.annotations.Presubmit
+import android.platform.test.annotations.RequiresDevice
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import com.android.window.flags.Flags
+import org.junit.Assume
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app with bottom half layout via [onUserLeaveHint] and by navigating to
+ * home.
+ *
+ * To run this test: `atest WMShellFlickerTestsPip:BottomHalfEnterPipOnUserLeaveHintTest`
+ *
+ * Actions:
+ * ```
+ *     Launch [BottomHalfPipLaunchingActivity] in full screen
+ *     Launch [BottomHalfPipActivity] with bottom half layout
+ *     Select "Via code behind" radio button
+ *     Press Home button or swipe up to go Home and put [pipApp] in pip mode
+ * ```
+ * Notes:
+ * ```
+ *     1. All assertions are inherited from [EnterPipTest]
+ *     2. Part of the test setup occurs automatically via
+ *        [android.tools.flicker.legacy.runner.TransitionRunner],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2.
+@RequiresFlagsDisabled(com.android.wm.shell.Flags.FLAG_ENABLE_PIP2)
+@RequiresFlagsEnabled(Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY)
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class BottomHalfEnterPipOnUserLeaveHintTest(flicker: LegacyFlickerTest) :
+    BottomHalfEnterPipTransition(flicker)
+{
+    override val thisTransition: FlickerBuilder.() -> Unit = { transitions {
+        tapl.goHome()
+        pipApp.waitForPip(wmHelper)
+    } }
+
+    override val defaultEnterPip: FlickerBuilder.() -> Unit = {
+        setup {
+            pipApp.launchViaIntent(wmHelper)
+            pipApp.enableEnterPipOnUserLeaveHint()
+        }
+    }
+
+    // gestural navigation
+
+    // TODO(b/385086051): check if we can remove optional = true in the test.
+    @Presubmit
+    @Test
+    fun pipAppWindowVisibleChanges() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        flicker.assertWm {
+            this.isAppWindowVisible(pipApp)
+                .then()
+                .isAppWindowInvisible(pipApp, isOptional = true)
+                .then()
+                .isAppWindowVisible(pipApp, isOptional = true)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun pipAppLayerVisibleChanges() {
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        // pip layer in gesture nav will disappear during transition
+        flicker.assertLayers {
+            this.isVisible(pipApp).then().isInvisible(pipApp).then().isVisible(pipApp)
+        }
+    }
+
+    @Presubmit
+    @Test
+    fun pipLayerRemainInsideVisibleBounds() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeTrue(flicker.scenario.isGesturalNavigation)
+        // pip layer in gesture nav will disappear during transition
+        flicker.assertLayersStart { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
+        flicker.assertLayersEnd { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
+    }
+
+    // 3-button navigation
+
+    @Presubmit
+    @Test
+    override fun pipAppWindowAlwaysVisible() {
+        // In gestural nav the pip will first move behind home and then above home. The visual
+        // appearance visible->invisible->visible is asserted by pipAppLayerAlwaysVisible().
+        // But the internal states of activity don't need to follow that, such as a temporary
+        // visibility state can be changed quickly outside a transaction so the test doesn't
+        // detect that. Hence, skip the case to avoid restricting the internal implementation.
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipAppWindowAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipAppLayerAlwaysVisible() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipAppLayerAlwaysVisible()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipOverlayLayerAppearThenDisappear() {
+        // no overlay in gesture nav for non-auto enter PiP transition
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipOverlayLayerAppearThenDisappear()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipLayerReduces() {
+        // in gestural nav the pip enters through alpha animation
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipLayerReduces()
+    }
+
+    @Presubmit
+    @Test
+    override fun focusChanges() {
+        // in gestural nav the focus goes to different activity on swipe up
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.focusChanges()
+    }
+
+    @Presubmit
+    @Test
+    override fun pipLayerOrOverlayRemainInsideVisibleBounds() {
+        // pip layer in gesture nav will disappear during transition
+        Assume.assumeFalse(flicker.scenario.isGesturalNavigation)
+        super.pipLayerOrOverlayRemainInsideVisibleBounds()
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipTransition.kt
new file mode 100644
index 0000000..a455de9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipTransition.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip.nonmatchparent
+
+import android.platform.test.annotations.Presubmit
+import android.tools.flicker.legacy.LegacyFlickerTest
+import com.android.server.wm.flicker.helpers.BottomHalfPipAppHelper
+import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.wm.shell.flicker.pip.common.EnterPipTransition
+import org.junit.Test
+
+/**
+ * The base class to test enter PIP animation on bottom half activity.
+ */
+abstract class BottomHalfEnterPipTransition(flicker: LegacyFlickerTest) :
+    EnterPipTransition(flicker)
+{
+    override val pipApp: PipAppHelper = BottomHalfPipAppHelper(
+        instrumentation,
+        useLaunchingActivity = true
+    )
+
+    @Presubmit
+    @Test
+    override fun pipWindowRemainInsideVisibleBounds() {
+        // We only verify the start and end because we update the layout when
+        // the BottomHalfPipActivity goes to PIP mode, which may lead to intermediate state that
+        // the window frame may be out of the display frame.
+        flicker.assertWmStart { visibleRegion(pipApp).coversAtMost(displayBounds) }
+        flicker.assertLayersEnd { visibleRegion(pipApp).coversAtMost(displayBounds) }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipViaAppUiButtonTest.kt
new file mode 100644
index 0000000..cfdd4e5
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipViaAppUiButtonTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker.pip.nonmatchparent
+
+import android.platform.test.annotations.Presubmit
+import android.platform.test.annotations.RequiresDevice
+import android.platform.test.annotations.RequiresFlagsDisabled
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.traces.parsers.toFlickerComponent
+import com.android.server.wm.flicker.testapp.ActivityOptions.BottomHalfPip.LAUNCHING_APP_COMPONENT
+import com.android.window.flags.Flags
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test entering pip from an app by interacting with the app UI
+ *
+ * To run this test: `atest WMShellFlickerTestsPip:BottomHalfEnterPipViaAppUiButtonTest`
+ *
+ * Actions:
+ * ```
+ *     Launch [BottomHalfPipLaunchingActivity] in full screen
+ *     Launch [BottomHalfPipActivity] with bottom half layout
+ *     Press an "enter pip" button to put [pipApp] in pip mode
+ * ```
+ *
+ * Notes:
+ * ```
+ *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
+ *        are inherited from [PipTransition]
+ *     2. Part of the test setup occurs automatically via
+ *        [android.tools.flicker.legacy.runner.TransitionRunner],
+ *        including configuring navigation mode, initial orientation and ensuring no
+ *        apps are running before setup
+ * ```
+ */
+// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2.
+@RequiresFlagsDisabled(com.android.wm.shell.Flags.FLAG_ENABLE_PIP2)
+@RequiresFlagsEnabled(Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY)
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class BottomHalfEnterPipViaAppUiButtonTest(flicker: LegacyFlickerTest) :
+    BottomHalfEnterPipTransition(flicker)
+{
+    override val thisTransition: FlickerBuilder.() -> Unit = {
+        transitions { pipApp.clickEnterPipButton(wmHelper) }
+    }
+
+    /**
+     * Checks if the focus changes to the launching activity behind when the bottom half [pipApp]
+     * goes to PIP mode.
+     */
+    @Presubmit
+    @Test
+    override fun focusChanges() {
+        flicker.assertEventLog {
+            this.focusChanges(
+                pipApp.packageName,
+                LAUNCHING_APP_COMPONENT.packageName
+            )
+        }
+    }
+
+    @Presubmit
+    @Test
+    override fun launcherLayerBecomesVisible() {
+        // Disable the test since the background activity is BottomHalfPipLaunchingActivity.
+    }
+
+    /**
+     * Checks if the launching activity behind the bottom half [pipApp] is always visible during
+     * the transition.
+     */
+    @Presubmit
+    @Test
+    fun launchingAppLayerAlwaysVisible() {
+        flicker.assertLayers { isVisible(LAUNCHING_APP_COMPONENT.toFlickerComponent()) }
+    }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
index 1f2eaa6..eeb83df 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
@@ -33,10 +33,10 @@
 import com.android.wm.shell.ShellTaskOrganizer
 import com.android.wm.shell.ShellTestCase
 import com.android.wm.shell.TestShellExecutor
-import com.android.wm.shell.WindowManagerShellWrapper
 import com.android.wm.shell.bubbles.bar.BubbleBarLayerView
 import com.android.wm.shell.bubbles.properties.BubbleProperties
 import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayImeController
 import com.android.wm.shell.common.DisplayInsetsController
 import com.android.wm.shell.common.FloatingContentCoordinator
 import com.android.wm.shell.common.ShellExecutor
@@ -123,7 +123,8 @@
                 mock<BubbleDataRepository>(),
                 mock<IStatusBarService>(),
                 windowManager,
-                WindowManagerShellWrapper(mainExecutor),
+                mock<DisplayInsetsController>(),
+                mock<DisplayImeController>(),
                 mock<UserManager>(),
                 mock<LauncherApps>(),
                 bubbleLogger,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index ecf766d..784e190 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -62,6 +62,7 @@
 import com.android.wm.shell.desktopmode.DesktopUserRepositories;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.FocusTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 
 import dagger.Lazy;
@@ -127,6 +128,8 @@
     private DesktopUserRepositories mDesktopUserRepositories;
     @Mock
     private DesktopRepository mDesktopRepository;
+    @Mock
+    private FocusTransitionObserver mFocusTransitionObserver;
 
     @Captor
     ArgumentCaptor<OnInsetsChangedListener> mOnInsetsChangedListenerCaptor;
@@ -162,7 +165,8 @@
                 mMockDisplayController, mMockDisplayInsetsController, mMockImeController,
                 mMockSyncQueue, mMockExecutor, mMockTransitionsLazy, mDockStateReader,
                 mCompatUIConfiguration, mCompatUIShellCommandHandler, mAccessibilityManager,
-                mCompatUIStatusManager, Optional.of(mDesktopUserRepositories)) {
+                mCompatUIStatusManager, Optional.of(mDesktopUserRepositories),
+                mFocusTransitionObserver) {
             @Override
             CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
                     ShellTaskOrganizer.TaskListener taskListener) {
@@ -280,6 +284,7 @@
         doReturn(false).when(mMockRestartDialogLayout).updateCompatInfo(any(), any(), anyBoolean());
 
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
 
         verify(mController).createCompatUiWindowManager(any(), eq(taskInfo), eq(mMockTaskListener));
@@ -411,6 +416,7 @@
         // Verify button remains hidden while IME is showing.
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
                 /* canShow= */ false);
@@ -443,6 +449,7 @@
         // Verify button remains hidden while keyguard is showing.
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         verify(mMockCompatLayout).updateCompatInfo(taskInfo, mMockTaskListener,
                 /* canShow= */ false);
@@ -523,6 +530,7 @@
     @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
     public void testRestartLayoutRecreatedIfNeeded() {
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
         doReturn(true).when(mMockRestartDialogLayout)
                 .needsToBeRecreated(any(TaskInfo.class),
                         any(ShellTaskOrganizer.TaskListener.class));
@@ -538,6 +546,7 @@
     @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
     public void testRestartLayoutNotRecreatedIfNotNeeded() {
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
         doReturn(false).when(mMockRestartDialogLayout)
                 .needsToBeRecreated(any(TaskInfo.class),
                         any(ShellTaskOrganizer.TaskListener.class));
@@ -558,7 +567,8 @@
 
         // Create new task
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ true);
+                /* isVisible */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo);
@@ -574,7 +584,8 @@
     public void testUpdateActiveTaskInfo_newTask_notVisibleOrFocused_notUpdated() {
         // Create new task
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ true);
+                /* isVisible */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate task being shown
         mController.updateActiveTaskInfo(taskInfo);
@@ -592,7 +603,8 @@
 
         // Create visible but NOT focused task
         final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ false);
+                /* isVisible */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo1);
@@ -604,7 +616,8 @@
 
         // Create focused but NOT visible task
         final TaskInfo taskInfo2 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
-                /* isVisible */ false, /* isFocused */ true);
+                /* isVisible */ false);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo2);
@@ -616,7 +629,8 @@
 
         // Create NOT focused but NOT visible task
         final TaskInfo taskInfo3 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
-                /* isVisible */ false, /* isFocused */ false);
+                /* isVisible */ false);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo3);
@@ -632,7 +646,8 @@
     public void testUpdateActiveTaskInfo_sameTask_notUpdated() {
         // Create new task
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ true);
+                /* isVisible */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo);
@@ -660,7 +675,8 @@
     public void testUpdateActiveTaskInfo_transparentTask_notUpdated() {
         // Create new task
         final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ true);
+                /* isVisible */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo);
@@ -678,7 +694,8 @@
 
         // Create transparent task
         final TaskInfo taskInfo1 = createTaskInfo(DISPLAY_ID, newTaskId, /* hasSizeCompat= */ true,
-                /* isVisible */ true, /* isFocused */ true, /* isTopActivityTransparent */ true);
+                /* isVisible */ true, /* isTopActivityTransparent */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(true);
 
         // Simulate new task being shown
         mController.updateActiveTaskInfo(taskInfo1);
@@ -694,6 +711,7 @@
     public void testLetterboxEduLayout_notCreatedWhenLetterboxEducationIsDisabled() {
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
         taskInfo.appCompatTaskInfo.setLetterboxEducationEnabled(false);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
 
@@ -707,6 +725,7 @@
     public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagEnabled() {
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
         when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
 
@@ -725,6 +744,7 @@
     public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagDisabled() {
         when(mDesktopUserRepositories.getCurrent().getVisibleTaskCount(DISPLAY_ID)).thenReturn(0);
         TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+        when(mFocusTransitionObserver.hasGlobalFocus((RunningTaskInfo) taskInfo)).thenReturn(false);
 
         mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
 
@@ -739,23 +759,22 @@
 
     private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat) {
         return createTaskInfo(displayId, taskId, hasSizeCompat, /* isVisible */ false,
-                /* isFocused */ false, /* isTopActivityTransparent */ false);
+                /* isTopActivityTransparent */ false);
     }
 
     private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
-            boolean isVisible, boolean isFocused) {
+            boolean isVisible) {
         return createTaskInfo(displayId, taskId, hasSizeCompat,
-                isVisible, isFocused, /* isTopActivityTransparent */ false);
+                isVisible, /* isTopActivityTransparent */ false);
     }
 
     private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
-            boolean isVisible, boolean isFocused, boolean isTopActivityTransparent) {
+            boolean isVisible, boolean isTopActivityTransparent) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
         taskInfo.taskId = taskId;
         taskInfo.displayId = displayId;
         taskInfo.appCompatTaskInfo.setTopActivityInSizeCompat(hasSizeCompat);
         taskInfo.isVisible = isVisible;
-        taskInfo.isFocused = isFocused;
         taskInfo.isTopActivityTransparent = isTopActivityTransparent;
         taskInfo.appCompatTaskInfo.setLetterboxEducationEnabled(true);
         taskInfo.appCompatTaskInfo.setTopActivityLetterboxed(true);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
index abd7078..c0ff2f0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
@@ -45,6 +45,7 @@
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -77,6 +78,12 @@
         doReturn(DISPLAY_HEIGHT).whenever(displayLayout).height()
     }
 
+    @After
+    fun tearDown() {
+        clearInvocations(staticMockMarker(FrameworkStatsLog::class.java))
+        clearInvocations(staticMockMarker(EventLogTags::class.java))
+    }
+
     @Test
     fun logSessionEnter_logsEnterReasonWithNewSessionId() {
         desktopModeEventLogger.logSessionEnter(EnterReason.KEYBOARD_SHORTCUT_ENTER)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
index 43684fb..4317143 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeLoggerTransitionObserverTest.kt
@@ -46,7 +46,9 @@
 import com.android.wm.shell.common.ShellExecutor
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.MinimizeReason
 import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_FROM_OVERVIEW
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_APP_HANDLE_MENU_BUTTON
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_ENTER_DESKTOP_FROM_KEYBOARD_SHORTCUT
@@ -174,7 +176,7 @@
         val change = createChange(TRANSIT_TO_FRONT, createTaskInfo(WINDOWING_MODE_FREEFORM))
         // task change is finalised when drag ends
         val transitionInfo =
-            TransitionInfoBuilder(Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, 0)
+            TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, 0)
                 .addChange(change)
                 .build()
 
@@ -435,7 +437,7 @@
         // desktop right after turning the screen on, we move to fullscreen then move another task
         // to desktop
         val transitionInfo =
-            TransitionInfoBuilder(Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, 0)
+            TransitionInfoBuilder(TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP, 0)
                 .addChange(createChange(TRANSIT_TO_FRONT, freeformTask))
                 .build()
         callOnTransitionReady(transitionInfo)
@@ -508,6 +510,20 @@
     }
 
     @Test
+    fun transitExitBackGesture_logTaskRemovedAndExitReasonTaskMovedToBack() {
+        // add a freeform task
+        transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
+        transitionObserver.isSessionActive = true
+
+        // task moved to back
+        val change = createChange(TRANSIT_TO_BACK, createTaskInfo(WINDOWING_MODE_FREEFORM))
+        val transitionInfo = TransitionInfoBuilder(TRANSIT_TO_BACK).addChange(change).build()
+        callOnTransitionReady(transitionInfo)
+
+        verifyTaskRemovedAndExitLogging(ExitReason.TASK_MOVED_TO_BACK, DEFAULT_TASK_UPDATE)
+    }
+
+    @Test
     fun transitExitDesktopUnknown_logTaskRemovedAndExitReasonUnknown() {
         // add a freeform task
         transitionObserver.addTaskInfosToCachedMap(createTaskInfo(WINDOWING_MODE_FREEFORM))
@@ -566,7 +582,10 @@
 
         assertFalse(transitionObserver.isSessionActive)
         verify(desktopModeEventLogger, times(1)).logSessionExit(eq(ExitReason.TASK_MINIMIZED))
-        verify(desktopModeEventLogger, times(1)).logTaskRemoved(eq(DEFAULT_TASK_UPDATE))
+        verify(desktopModeEventLogger, times(1))
+            .logTaskRemoved(
+                eq(DEFAULT_TASK_UPDATE.copy(minimizeReason = MinimizeReason.MINIMIZE_BUTTON))
+            )
         verifyZeroInteractions(desktopModeEventLogger)
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index 4f37180b..fe08526 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -82,6 +82,7 @@
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.window.flags.Flags
 import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE
+import com.android.window.flags.Flags.FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS
 import com.android.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP
 import com.android.window.flags.Flags.FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT
 import com.android.window.flags.Flags.FLAG_ENABLE_PER_DISPLAY_DESKTOP_WALLPAPER_ACTIVITY
@@ -110,6 +111,7 @@
 import com.android.wm.shell.desktopmode.EnterDesktopTaskTransitionHandler.FREEFORM_ANIMATION_DURATION
 import com.android.wm.shell.desktopmode.ExitDesktopTaskTransitionHandler.FULLSCREEN_ANIMATION_DURATION
 import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
 import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler
 import com.android.wm.shell.desktopmode.persistence.Desktop
 import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
@@ -235,6 +237,10 @@
     @Mock
     lateinit var desktopModeEnterExitTransitionListener: DesktopModeEntryExitTransitionListener
     @Mock private lateinit var userManager: UserManager
+    @Mock
+    private lateinit var desktopWallpaperActivityTokenProvider:
+        DesktopWallpaperActivityTokenProvider
+
     private lateinit var controller: DesktopTasksController
     private lateinit var shellInit: ShellInit
     private lateinit var taskRepository: DesktopRepository
@@ -256,6 +262,7 @@
     private val RESIZABLE_PORTRAIT_BOUNDS = Rect(680, 75, 1880, 1275)
     private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 449, 1575, 1611)
     private val UNRESIZABLE_PORTRAIT_BOUNDS = Rect(830, 75, 1730, 1275)
+    private val wallpaperToken = MockToken().token()
 
     @Before
     fun setUp() {
@@ -323,6 +330,7 @@
                 )
             )
             .thenReturn(ExitResult.NoExit)
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(wallpaperToken)
 
         controller = createController()
         controller.setSplitScreenController(splitScreenController)
@@ -374,6 +382,7 @@
             desktopModeEventLogger,
             desktopModeUiEventLogger,
             desktopTilingDecorViewModel,
+            desktopWallpaperActivityTokenProvider,
         )
     }
 
@@ -1485,11 +1494,9 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun moveToFullscreen_tdaFullscreen_windowingModeUndefined_removesWallpaperActivity() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-
-        taskRepository.wallpaperActivityToken = wallpaperToken
         assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
             .configuration
             .windowConfiguration
@@ -1503,7 +1510,7 @@
             .onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
         assertThat(taskChange.windowingMode).isEqualTo(WINDOWING_MODE_UNDEFINED)
         // Removes wallpaper activity when leaving desktop
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -1520,11 +1527,10 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun moveToFullscreen_tdaFreeform_windowingModeFullscreen_removesWallpaperActivity() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
             .configuration
             .windowConfiguration
@@ -1538,7 +1544,7 @@
         verify(desktopModeEnterExitTransitionListener)
             .onExitDesktopModeTransitionStarted(FULLSCREEN_ANIMATION_DURATION)
         // Removes wallpaper activity when leaving desktop
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -1546,9 +1552,7 @@
         val task1 = setUpFreeformTask()
         // Setup task2
         setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         assertNotNull(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
             .configuration
             .windowConfiguration
@@ -1703,13 +1707,14 @@
 
         val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         controller.moveToNextDisplay(task.taskId)
-        with(getLatestWct(type = TRANSIT_CHANGE)) {
-            assertThat(hierarchyOps).hasSize(1)
-            assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
-            assertThat(hierarchyOps[0].isReparent).isTrue()
-            assertThat(hierarchyOps[0].newParent).isEqualTo(secondDisplayArea.token.asBinder())
-            assertThat(hierarchyOps[0].toTop).isTrue()
-        }
+
+        val taskChange =
+            getLatestWct(type = TRANSIT_CHANGE).hierarchyOps.find {
+                it.container == task.token.asBinder() && it.isReparent
+            }
+        assertNotNull(taskChange)
+        assertThat(taskChange.newParent).isEqualTo(secondDisplayArea.token.asBinder())
+        assertThat(taskChange.toTop).isTrue()
     }
 
     @Test
@@ -1725,13 +1730,13 @@
         val task = setUpFreeformTask(displayId = SECOND_DISPLAY)
         controller.moveToNextDisplay(task.taskId)
 
-        with(getLatestWct(type = TRANSIT_CHANGE)) {
-            assertThat(hierarchyOps).hasSize(1)
-            assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
-            assertThat(hierarchyOps[0].isReparent).isTrue()
-            assertThat(hierarchyOps[0].newParent).isEqualTo(defaultDisplayArea.token.asBinder())
-            assertThat(hierarchyOps[0].toTop).isTrue()
-        }
+        val taskChange =
+            getLatestWct(type = TRANSIT_CHANGE).hierarchyOps.find {
+                it.container == task.token.asBinder() && it.isReparent
+            }
+        assertNotNull(taskChange)
+        assertThat(taskChange.newParent).isEqualTo(defaultDisplayArea.token.asBinder())
+        assertThat(taskChange.toTop).isTrue()
     }
 
     @Test
@@ -1746,8 +1751,6 @@
             .thenReturn(secondDisplayArea)
         // Add a task and a wallpaper
         val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         controller.moveToNextDisplay(task.taskId)
 
@@ -1908,6 +1911,32 @@
     }
 
     @Test
+    @EnableFlags(
+        FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS,
+        FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT,
+    )
+    fun moveToNextDisplay_destinationGainGlobalFocus() {
+        // Set up two display ids
+        whenever(rootTaskDisplayAreaOrganizer.displayIds)
+            .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
+        // Create a mock for the target display area: second display
+        val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
+        whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
+            .thenReturn(secondDisplayArea)
+
+        val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+        controller.moveToNextDisplay(task.taskId)
+
+        val taskChange =
+            getLatestWct(type = TRANSIT_CHANGE).hierarchyOps.find {
+                it.container == task.token.asBinder() && it.type == HIERARCHY_OP_TYPE_REORDER
+            }
+        assertNotNull(taskChange)
+        assertThat(taskChange.toTop).isTrue()
+        assertThat(taskChange.includingParents()).isTrue()
+    }
+
+    @Test
     fun getTaskWindowingMode() {
         val fullscreenTask = setUpFullscreenTask()
         val freeformTask = setUpFreeformTask()
@@ -1932,28 +1961,29 @@
     fun onDesktopWindowClose_singleActiveTask_noWallpaperActivityToken() {
         val task = setUpFreeformTask()
         val wct = WindowContainerTransaction()
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
+
         controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
+
         // Doesn't modify transaction
         assertThat(wct.hierarchyOps).isEmpty()
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun onDesktopWindowClose_singleActiveTask_hasWallpaperActivityToken() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         val wct = WindowContainerTransaction()
         controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
         // Adds remove wallpaper operation
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
     fun onDesktopWindowClose_singleActiveTask_isClosing() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
+
         taskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
 
         val wct = WindowContainerTransaction()
@@ -1965,8 +1995,7 @@
     @Test
     fun onDesktopWindowClose_singleActiveTask_isMinimized() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
+
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
 
         val wct = WindowContainerTransaction()
@@ -1979,8 +2008,6 @@
     fun onDesktopWindowClose_multipleActiveTasks() {
         val task1 = setUpFreeformTask()
         setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         val wct = WindowContainerTransaction()
         controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
@@ -1989,31 +2016,31 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun onDesktopWindowClose_multipleActiveTasks_isOnlyNonClosingTask() {
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
+
         taskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
 
         val wct = WindowContainerTransaction()
         controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
         // Adds remove wallpaper operation
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun onDesktopWindowClose_multipleActiveTasks_hasMinimized() {
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
+
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
 
         val wct = WindowContainerTransaction()
         controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
         // Adds remove wallpaper operation
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2022,8 +2049,6 @@
         val transition = Binder()
         whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
             .thenReturn(transition)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         controller.minimizeTask(task)
 
@@ -2075,13 +2100,12 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun onTaskMinimize_singleActiveTask_hasWallpaperActivityToken_removesWallpaper() {
         val task = setUpFreeformTask()
         val transition = Binder()
         whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
             .thenReturn(transition)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         // The only active task is being minimized.
         controller.minimizeTask(task)
@@ -2089,7 +2113,7 @@
         val captor = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
         verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
         // Adds remove wallpaper operation
-        captor.value.assertRemoveAt(index = 0, wallpaperToken)
+        captor.value.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2098,8 +2122,6 @@
         val transition = Binder()
         whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
             .thenReturn(transition)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
 
         // The only active task is already minimized.
@@ -2119,8 +2141,6 @@
         val transition = Binder()
         whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
             .thenReturn(transition)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         controller.minimizeTask(task1)
 
@@ -2132,14 +2152,13 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun onDesktopWindowMinimize_multipleActiveTasks_minimizesTheOnlyVisibleTask_removesWallpaper() {
         val task1 = setUpFreeformTask(active = true)
         val task2 = setUpFreeformTask(active = true)
         val transition = Binder()
         whenever(freeformTaskTransitionStarter.startMinimizedModeTransition(any()))
             .thenReturn(transition)
-        val wallpaperToken = MockToken().token()
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
 
         // task1 is the only visible task as task2 is minimized.
@@ -2148,7 +2167,7 @@
         val captor = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
         verify(freeformTaskTransitionStarter).startMinimizedModeTransition(captor.capture())
         // Adds remove wallpaper operation
-        captor.value.assertRemoveAt(index = 0, wallpaperToken)
+        captor.value.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2748,6 +2767,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
     fun handleRequest_backTransition_singleTaskNoToken_withWallpaper_removesTask() {
         val task = setUpFreeformTask()
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
 
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
@@ -2771,6 +2791,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
     fun handleRequest_backTransition_singleTaskNoToken_doesNotHandle() {
         val task = setUpFreeformTask()
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
 
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
@@ -2783,7 +2804,6 @@
     fun handleRequest_backTransition_singleTaskWithToken_noWallpaper_doesNotHandle() {
         val task = setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
 
@@ -2791,17 +2811,19 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    @EnableFlags(
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
+    )
     fun handleRequest_backTransition_singleTaskWithToken_removesWallpaper() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_TO_BACK))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2810,7 +2832,6 @@
         val task1 = setUpFreeformTask()
         setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
 
@@ -2823,7 +2844,6 @@
         val task1 = setUpFreeformTask()
         setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
 
@@ -2834,35 +2854,37 @@
     @EnableFlags(
         Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
         Flags.FLAG_ENABLE_DESKTOP_WINDOWING_BACK_NAVIGATION,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
     )
     fun handleRequest_backTransition_multipleTasksSingleNonClosing_removesWallpaperAndTask() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    @EnableFlags(
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
+    )
     fun handleRequest_backTransition_multipleTasksSingleNonMinimized_removesWallpaperAndTask() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_TO_BACK))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2870,9 +2892,7 @@
     fun handleRequest_backTransition_nonMinimizadTask_withWallpaper_removesWallpaper() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         // Task is being minimized so mark it as not visible.
         taskRepository.updateTask(displayId = DEFAULT_DISPLAY, task2.taskId, isVisible = false)
@@ -2897,6 +2917,7 @@
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
     fun handleRequest_closeTransition_singleTaskNoToken_doesNotHandle() {
         val task = setUpFreeformTask()
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(null)
 
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
@@ -2909,7 +2930,6 @@
     fun handleRequest_closeTransition_singleTaskWithToken_noWallpaper_doesNotHandle() {
         val task = setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
 
@@ -2917,17 +2937,19 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    @EnableFlags(
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
+    )
     fun handleRequest_closeTransition_singleTaskWithToken_withWallpaper_removesWallpaper() {
         val task = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         val result =
             controller.handleRequest(Binder(), createTransition(task, type = TRANSIT_CLOSE))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2936,7 +2958,6 @@
         val task1 = setUpFreeformTask()
         setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
 
@@ -2949,7 +2970,6 @@
         val task1 = setUpFreeformTask()
         setUpFreeformTask()
 
-        taskRepository.wallpaperActivityToken = MockToken().token()
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
 
@@ -2957,35 +2977,39 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    @EnableFlags(
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
+    )
     fun handleRequest_closeTransition_multipleTasksSingleNonClosing_removesWallpaper() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.addClosingTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
+    @EnableFlags(
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY,
+        Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER,
+    )
     fun handleRequest_closeTransition_multipleTasksSingleNonMinimized_removesWallpaper() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         val result =
             controller.handleRequest(Binder(), createTransition(task1, type = TRANSIT_CLOSE))
 
         // Should create remove wallpaper transaction
-        assertNotNull(result, "Should handle request").assertRemoveAt(index = 0, wallpaperToken)
+        assertNotNull(result, "Should handle request")
+            .assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -2993,9 +3017,7 @@
     fun handleRequest_closeTransition_minimizadTask_withWallpaper_removesWallpaper() {
         val task1 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
         val task2 = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
-        val wallpaperToken = MockToken().token()
 
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = task2.taskId)
         // Task is being minimized so mark it as not visible.
         taskRepository.updateTask(displayId = DEFAULT_DISPLAY, task2.taskId, isVisible = false)
@@ -3067,16 +3089,15 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun moveFocusedTaskToFullscreen_onlyVisibleNonMinimizedTask_removesWallpaperActivity() {
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
         val task3 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
         task1.isFocused = false
         task2.isFocused = true
         task3.isFocused = false
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
         taskRepository.updateTask(DEFAULT_DISPLAY, task3.taskId, isVisible = false)
 
@@ -3086,7 +3107,7 @@
         val taskChange = assertNotNull(wct.changes[task2.token.asBinder()])
         assertThat(taskChange.windowingMode)
             .isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -3094,12 +3115,10 @@
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
         val task3 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
         task1.isFocused = false
         task2.isFocused = true
         task3.isFocused = false
-        taskRepository.wallpaperActivityToken = wallpaperToken
         controller.enterFullscreen(DEFAULT_DISPLAY, transitionSource = UNKNOWN)
 
         val wct = getLatestExitDesktopWct()
@@ -3582,16 +3601,15 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun enterSplit_onlyVisibleNonMinimizedTask_removesWallpaperActivity() {
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
         val task3 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
         task1.isFocused = false
         task2.isFocused = true
         task3.isFocused = false
-        taskRepository.wallpaperActivityToken = wallpaperToken
         taskRepository.minimizeTask(DEFAULT_DISPLAY, task1.taskId)
         taskRepository.updateTask(DEFAULT_DISPLAY, task3.taskId, isVisible = false)
 
@@ -3606,7 +3624,7 @@
                 eq(task2.configuration.windowConfiguration.bounds),
             )
         // Removes wallpaper activity when leaving desktop
-        wctArgument.value.assertRemoveAt(index = 0, wallpaperToken)
+        wctArgument.value.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -3614,12 +3632,10 @@
         val task1 = setUpFreeformTask()
         val task2 = setUpFreeformTask()
         val task3 = setUpFreeformTask()
-        val wallpaperToken = MockToken().token()
 
         task1.isFocused = false
         task2.isFocused = true
         task3.isFocused = false
-        taskRepository.wallpaperActivityToken = wallpaperToken
 
         controller.enterSplit(DEFAULT_DISPLAY, leftOrTop = false)
 
@@ -4160,8 +4176,7 @@
                         screenOrientation = SCREEN_ORIENTATION_LANDSCAPE
                         configuration.windowConfiguration.appBounds = bounds
                     }
-                appCompatTaskInfo.topActivityLetterboxAppWidth = bounds.width()
-                appCompatTaskInfo.topActivityLetterboxAppHeight = bounds.height()
+                appCompatTaskInfo.topActivityAppBounds.set(0, 0, bounds.width(), bounds.height())
                 isResizeable = false
             }
 
@@ -4879,15 +4894,19 @@
             appCompatTaskInfo.isSystemFullscreenOverrideEnabled = enableSystemFullscreenOverride
 
             if (deviceOrientation == ORIENTATION_LANDSCAPE) {
-                configuration.windowConfiguration.appBounds =
-                    Rect(0, 0, DISPLAY_DIMENSION_LONG, DISPLAY_DIMENSION_SHORT)
-                appCompatTaskInfo.topActivityLetterboxAppWidth = DISPLAY_DIMENSION_LONG
-                appCompatTaskInfo.topActivityLetterboxAppHeight = DISPLAY_DIMENSION_SHORT
+                appCompatTaskInfo.topActivityAppBounds.set(
+                    0,
+                    0,
+                    DISPLAY_DIMENSION_LONG,
+                    DISPLAY_DIMENSION_SHORT,
+                )
             } else {
-                configuration.windowConfiguration.appBounds =
-                    Rect(0, 0, DISPLAY_DIMENSION_SHORT, DISPLAY_DIMENSION_LONG)
-                appCompatTaskInfo.topActivityLetterboxAppWidth = DISPLAY_DIMENSION_SHORT
-                appCompatTaskInfo.topActivityLetterboxAppHeight = DISPLAY_DIMENSION_LONG
+                appCompatTaskInfo.topActivityAppBounds.set(
+                    0,
+                    0,
+                    DISPLAY_DIMENSION_SHORT,
+                    DISPLAY_DIMENSION_LONG,
+                )
             }
 
             if (shouldLetterbox) {
@@ -4897,17 +4916,15 @@
                         screenOrientation == SCREEN_ORIENTATION_PORTRAIT
                 ) {
                     // Letterbox to portrait size
-                    appCompatTaskInfo.setTopActivityLetterboxed(true)
-                    appCompatTaskInfo.topActivityLetterboxAppWidth = 1200
-                    appCompatTaskInfo.topActivityLetterboxAppHeight = 1600
+                    appCompatTaskInfo.isTopActivityLetterboxed = true
+                    appCompatTaskInfo.topActivityAppBounds.set(0, 0, 1200, 1600)
                 } else if (
                     deviceOrientation == ORIENTATION_PORTRAIT &&
                         screenOrientation == SCREEN_ORIENTATION_LANDSCAPE
                 ) {
                     // Letterbox to landscape size
-                    appCompatTaskInfo.setTopActivityLetterboxed(true)
-                    appCompatTaskInfo.topActivityLetterboxAppWidth = 1600
-                    appCompatTaskInfo.topActivityLetterboxAppHeight = 1200
+                    appCompatTaskInfo.isTopActivityLetterboxed = true
+                    appCompatTaskInfo.topActivityAppBounds.set(0, 0, 1600, 1200)
                 }
             }
         }
@@ -5062,6 +5079,18 @@
     toTop?.let { assertThat(op.toTop).isEqualTo(it) }
 }
 
+private fun WindowContainerTransaction.assertReorderAt(
+    index: Int,
+    token: WindowContainerToken,
+    toTop: Boolean? = null,
+) {
+    assertIndexInBounds(index)
+    val op = hierarchyOps[index]
+    assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER)
+    assertThat(op.container).isEqualTo(token.asBinder())
+    toTop?.let { assertThat(op.toTop).isEqualTo(it) }
+}
+
 private fun WindowContainerTransaction.assertReorderSequence(vararg tasks: RunningTaskInfo) {
     for (i in tasks.indices) {
         assertReorderAt(i, tasks[i])
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
index e6f1fcf..52602f2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksLimiterTest.kt
@@ -551,7 +551,7 @@
             .getTransitionObserver()
             .onTransitionReady(
                 transition,
-                TransitionInfoBuilder(TRANSIT_OPEN).build(),
+                TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
                 StubTransaction() /* startTransaction */,
                 StubTransaction(), /* finishTransaction */
             )
@@ -583,7 +583,7 @@
             .getTransitionObserver()
             .onTransitionReady(
                 transition,
-                TransitionInfoBuilder(TRANSIT_OPEN).build(),
+                TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
                 StubTransaction() /* startTransaction */,
                 StubTransaction(), /* finishTransaction */
             )
@@ -616,7 +616,7 @@
             .getTransitionObserver()
             .onTransitionReady(
                 mergedTransition,
-                TransitionInfoBuilder(TRANSIT_OPEN).build(),
+                TransitionInfoBuilder(TRANSIT_OPEN).addChange(TRANSIT_TO_BACK, task).build(),
                 StubTransaction() /* startTransaction */,
                 StubTransaction(), /* finishTransaction */
             )
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
index c66d203..d491d44 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserverTest.kt
@@ -35,7 +35,7 @@
 import android.window.TransitionInfo.Change
 import android.window.WindowContainerToken
 import android.window.WindowContainerTransaction
-import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK
+import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
 import com.android.modules.utils.testing.ExtendedMockitoRule
 import com.android.window.flags.Flags
 import com.android.wm.shell.MockToken
@@ -43,6 +43,7 @@
 import com.android.wm.shell.back.BackAnimationController
 import com.android.wm.shell.common.ShellExecutor
 import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_EXIT_DESKTOP_MODE_TASK_DRAG
+import com.android.wm.shell.desktopmode.desktopwallpaperactivity.DesktopWallpaperActivityTokenProvider
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
 import com.android.wm.shell.sysui.ShellInit
 import com.android.wm.shell.transition.Transitions
@@ -87,6 +88,9 @@
     private val taskRepository = mock<DesktopRepository>()
     private val mixedHandler = mock<DesktopMixedTransitionHandler>()
     private val backAnimationController = mock<BackAnimationController>()
+    private val desktopWallpaperActivityTokenProvider =
+        mock<DesktopWallpaperActivityTokenProvider>()
+    private val wallpaperToken = MockToken().token()
 
     private lateinit var transitionObserver: DesktopTasksTransitionObserver
     private lateinit var shellInit: ShellInit
@@ -98,6 +102,7 @@
 
         whenever(userRepositories.current).thenReturn(taskRepository)
         whenever(userRepositories.getProfile(anyInt())).thenReturn(taskRepository)
+        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(wallpaperToken)
 
         transitionObserver =
             DesktopTasksTransitionObserver(
@@ -107,6 +112,7 @@
                 shellTaskOrganizer,
                 mixedHandler,
                 backAnimationController,
+                desktopWallpaperActivityTokenProvider,
                 shellInit,
             )
     }
@@ -233,12 +239,11 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_ON_SYSTEM_USER)
     fun closeLastTask_wallpaperTokenExists_wallpaperIsRemoved() {
         val mockTransition = Mockito.mock(IBinder::class.java)
         val task = createTaskInfo(1, WINDOWING_MODE_FREEFORM)
-        val wallpaperToken = MockToken().token()
         whenever(taskRepository.getVisibleTaskCount(task.displayId)).thenReturn(0)
-        whenever(taskRepository.wallpaperActivityToken).thenReturn(wallpaperToken)
 
         transitionObserver.onTransitionReady(
             transition = mockTransition,
@@ -248,9 +253,9 @@
         )
         transitionObserver.onTransitionFinished(mockTransition, false)
 
-        val wct = getLatestWct(type = TRANSIT_CLOSE)
+        val wct = getLatestWct(type = TRANSIT_TO_BACK)
         assertThat(wct.hierarchyOps).hasSize(1)
-        wct.assertRemoveAt(index = 0, wallpaperToken)
+        wct.assertReorderAt(index = 0, wallpaperToken, toTop = false)
     }
 
     @Test
@@ -377,11 +382,16 @@
         return arg.value
     }
 
-    private fun WindowContainerTransaction.assertRemoveAt(index: Int, token: WindowContainerToken) {
+    private fun WindowContainerTransaction.assertReorderAt(
+        index: Int,
+        token: WindowContainerToken,
+        toTop: Boolean? = null,
+    ) {
         assertIndexInBounds(index)
         val op = hierarchyOps[index]
-        assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REMOVE_TASK)
+        assertThat(op.type).isEqualTo(HIERARCHY_OP_TYPE_REORDER)
         assertThat(op.container).isEqualTo(token.asBinder())
+        toTop?.let { assertThat(op.toTop).isEqualTo(it) }
     }
 
     private fun WindowContainerTransaction.assertIndexInBounds(index: Int) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index e4eff9f..2216d54 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -25,14 +25,14 @@
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer
 import com.android.wm.shell.ShellTestCase
 import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
+import com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
 import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.Companion.DRAG_TO_DESKTOP_FINISH_ANIM_DURATION_MS
 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
 import com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
 import com.android.wm.shell.splitscreen.SplitScreenController
 import com.android.wm.shell.transition.Transitions
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_CANCEL_DRAG_TO_DESKTOP
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_END_DRAG_TO_DESKTOP
-import com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP
 import com.android.wm.shell.windowdecor.MoveToDesktopAnimator
 import java.util.function.Supplier
 import junit.framework.Assert.assertEquals
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragSessionTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragSessionTest.kt
index 3d59342..8ccca07 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragSessionTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragSessionTest.kt
@@ -59,6 +59,13 @@
     }
 
     @Test
+    fun testNullClipData() {
+        // Start a new drag session with null data
+        val session = DragSession(activityTaskManager, displayLayout, null, 0)
+        assertThat(session.hideDragSourceTaskId).isEqualTo(-1)
+    }
+
+    @Test
     fun testGetRunningTask() {
         // Set up running tasks
         val runningTasks = listOf(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
index 3fe8c10..a8aa257 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip2/phone/PipSchedulerTest.java
@@ -120,15 +120,22 @@
     @Test
     public void scheduleExitPipViaExpand_nullTaskToken_noop() {
         setNullPipTaskToken();
+        when(mMockPipTransitionState.isInPip()).thenReturn(true);
 
         mPipScheduler.scheduleExitPipViaExpand();
 
-        verify(mMockMainExecutor, never()).execute(any());
+        verify(mMockMainExecutor, times(1)).execute(mRunnableArgumentCaptor.capture());
+        assertNotNull(mRunnableArgumentCaptor.getValue());
+        mRunnableArgumentCaptor.getValue().run();
+
+        verify(mMockPipTransitionController, never())
+                .startExitTransition(eq(TRANSIT_EXIT_PIP), any(), isNull());
     }
 
     @Test
     public void scheduleExitPipViaExpand_exitTransitionCalled() {
         setMockPipTaskToken();
+        when(mMockPipTransitionState.isInPip()).thenReturn(true);
 
         mPipScheduler.scheduleExitPipViaExpand();
 
@@ -142,20 +149,13 @@
 
     @Test
     public void removePipAfterAnimation() {
-        //TODO: Update once this is changed to run animation as part of transition
         setMockPipTaskToken();
+        when(mMockPipTransitionState.isInPip()).thenReturn(true);
 
-        mPipScheduler.removePipAfterAnimation();
-        verify(mMockAlphaAnimator, times(1))
-                .setAnimationEndCallback(mRunnableArgumentCaptor.capture());
-        assertNotNull(mRunnableArgumentCaptor.getValue());
-        verify(mMockAlphaAnimator, times(1)).start();
-
-        mRunnableArgumentCaptor.getValue().run();
+        mPipScheduler.scheduleRemovePip();
 
         verify(mMockMainExecutor, times(1)).execute(mRunnableArgumentCaptor.capture());
         assertNotNull(mRunnableArgumentCaptor.getValue());
-
         mRunnableArgumentCaptor.getValue().run();
 
         verify(mMockPipTransitionController, times(1))
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index ce482cd..4b01d84 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -55,7 +55,6 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.testing.TestableContext;
-import android.view.InsetsState;
 import android.view.Surface;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
@@ -338,9 +337,7 @@
         windowInfo.appToken = appToken;
         windowInfo.targetActivityInfo = info;
         windowInfo.taskInfo = taskInfo;
-        windowInfo.topOpaqueWindowInsetsState = new InsetsState();
         windowInfo.mainWindowLayoutParams = new WindowManager.LayoutParams();
-        windowInfo.topOpaqueWindowLayoutParams = new WindowManager.LayoutParams();
         return windowInfo;
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index 8dfdfb4..8bdefa7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -25,7 +25,7 @@
 import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.wm.shell.transition.Transitions.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
+import static com.android.wm.shell.desktopmode.DesktopModeTransitionTypes.TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.mock;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index aead0a7..ffe8e71 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -1054,26 +1054,6 @@
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
-    fun testImmersiveButtonClick_entersImmersiveMode() {
-        val onClickListenerCaptor = forClass(View.OnClickListener::class.java)
-                as ArgumentCaptor<View.OnClickListener>
-        val decor = createOpenTaskDecoration(
-            windowingMode = WINDOWING_MODE_FREEFORM,
-            onCaptionButtonClickListener = onClickListenerCaptor,
-            requestingImmersive = true,
-        )
-        val view = mock(View::class.java)
-        whenever(view.id).thenReturn(R.id.maximize_window)
-        whenever(mockDesktopRepository.isTaskInFullImmersiveState(decor.mTaskInfo.taskId))
-            .thenReturn(false)
-
-        onClickListenerCaptor.value.onClick(view)
-
-        verify(mockDesktopImmersiveController).moveTaskToImmersive(decor.mTaskInfo)
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
     fun testImmersiveRestoreButtonClick_exitsImmersiveMode() {
         val onClickListenerCaptor = forClass(View.OnClickListener::class.java)
                 as ArgumentCaptor<View.OnClickListener>
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 855b3dd..e99e5cc 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
@@ -164,6 +164,13 @@
     private static final Uri TEST_URI3 = Uri.parse("https://slides.google.com/");
     private static final Uri TEST_URI4 = Uri.parse("https://calendar.google.com/");
 
+    private static final boolean DEFAULT_APPLY_START_TRANSACTION_ON_DRAW = true;
+    private static final boolean DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP = false;
+    private static final boolean DEFAULT_IS_STATUSBAR_VISIBLE = true;
+    private static final boolean DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED = false;
+    private static final boolean DEFAULT_IS_IN_FULL_IMMERSIVE_MODE = false;
+    private static final boolean DEFAULT_HAS_GLOBAL_FOCUS = true;
+
     @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
 
     @Mock
@@ -325,16 +332,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams, mContext, taskInfo, mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mShadowRadius)
                 .isNotEqualTo(WindowDecoration.INVALID_SHADOW_RADIUS);
@@ -346,16 +344,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams, mContext, taskInfo, mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mShadowRadius).isEqualTo(WindowDecoration.INVALID_SHADOW_RADIUS);
     }
@@ -366,16 +355,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams, mContext, taskInfo, mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mShadowRadius).isEqualTo(WindowDecoration.INVALID_SHADOW_RADIUS);
     }
@@ -387,19 +367,7 @@
         fillRoundedCornersResources(/* fillValue= */ 30);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mCornerRadius).isGreaterThan(0);
     }
@@ -411,19 +379,7 @@
         fillRoundedCornersResources(/* fillValue= */ 30);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mCornerRadius).isEqualTo(INVALID_CORNER_RADIUS);
     }
@@ -435,19 +391,7 @@
         fillRoundedCornersResources(/* fillValue= */ 30);
         RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mCornerRadius).isEqualTo(INVALID_CORNER_RADIUS);
     }
@@ -463,19 +407,7 @@
         taskInfo.configuration.densityDpi = customTaskDensity;
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(customTaskDensity);
     }
@@ -492,19 +424,7 @@
         taskInfo.configuration.densityDpi = customTaskDensity;
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(systemDensity);
     }
@@ -518,19 +438,7 @@
                 APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.hasInputFeatureSpy()).isTrue();
     }
@@ -544,19 +452,7 @@
                 APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isTrue();
     }
@@ -569,19 +465,7 @@
         taskInfo.taskDescription.setTopOpaqueSystemBarsAppearance(0);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
     }
@@ -594,19 +478,7 @@
         taskInfo.taskDescription.setTopOpaqueSystemBarsAppearance(0);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isFalse();
     }
@@ -618,19 +490,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
     }
@@ -642,19 +502,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mLimitTouchRegionToSystemAreas).isFalse();
     }
@@ -665,19 +513,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(hasNoInputChannelFeature(relayoutParams)).isFalse();
     }
@@ -689,19 +525,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
     }
@@ -713,19 +537,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
     }
@@ -738,19 +550,7 @@
         taskInfo.taskDescription.setTopOpaqueSystemBarsAppearance(0);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) != 0).isTrue();
     }
@@ -764,19 +564,7 @@
                 APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) == 0).isTrue();
     }
@@ -788,19 +576,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(
                 (relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) != 0)
@@ -814,19 +590,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(
                 (relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING_OPAQUE_CAPTION_BAR) == 0)
@@ -841,19 +605,7 @@
         when(mMockSplitScreenController.getSplitPosition(taskInfo.taskId))
                 .thenReturn(SPLIT_POSITION_BOTTOM_OR_RIGHT);
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ true,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         assertThat(relayoutParams.mIsInsetSource).isTrue();
     }
@@ -876,13 +628,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
+                DEFAULT_IS_STATUSBAR_VISIBLE,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
                 /* inFullImmersiveMode */ true,
                 insetsState,
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         // Takes status bar inset as padding, ignores caption bar inset.
@@ -901,13 +653,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
+                DEFAULT_IS_STATUSBAR_VISIBLE,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
                 /* inFullImmersiveMode */ true,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsInsetSource).isFalse();
@@ -925,13 +677,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
                 /* isStatusBarVisible */ false,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
+                DEFAULT_IS_IN_FULL_IMMERSIVE_MODE,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         // Header is always shown because it's assumed the status bar is always visible.
@@ -949,13 +701,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
                 /* isStatusBarVisible */ true,
                 /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
+                DEFAULT_IS_IN_FULL_IMMERSIVE_MODE,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isTrue();
@@ -972,13 +724,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
                 /* isStatusBarVisible */ false,
-                /* isKeyguardVisibleAndOccluded */ false,
-                /* inFullImmersiveMode */ false,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
+                DEFAULT_IS_IN_FULL_IMMERSIVE_MODE,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isFalse();
@@ -995,13 +747,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
+                DEFAULT_IS_STATUSBAR_VISIBLE,
                 /* isKeyguardVisibleAndOccluded */ true,
-                /* inFullImmersiveMode */ false,
+                DEFAULT_IS_IN_FULL_IMMERSIVE_MODE,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isFalse();
@@ -1019,13 +771,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
                 /* isStatusBarVisible */ true,
-                /* isKeyguardVisibleAndOccluded */ false,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
                 /* inFullImmersiveMode */ true,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isTrue();
@@ -1035,13 +787,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
                 /* isStatusBarVisible */ false,
-                /* isKeyguardVisibleAndOccluded */ false,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
                 /* inFullImmersiveMode */ true,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isFalse();
@@ -1059,13 +811,13 @@
                 mTestableContext,
                 taskInfo,
                 mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop */ false,
-                /* isStatusBarVisible */ true,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
+                DEFAULT_IS_STATUSBAR_VISIBLE,
                 /* isKeyguardVisibleAndOccluded */ true,
                 /* inFullImmersiveMode */ true,
                 new InsetsState(),
-                /* hasGlobalFocus= */ true,
+                DEFAULT_HAS_GLOBAL_FOCUS,
                 mExclusionRegion);
 
         assertThat(relayoutParams.mIsCaptionVisible).isFalse();
@@ -1078,19 +830,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop= */ false,
-                /* isStatusBarVisible= */ true,
-                /* isKeyguardVisibleAndOccluded= */ false,
-                /* inFullImmersiveMode= */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         // App Handles don't need to be rendered in sync with the task animation, per UX.
         assertThat(relayoutParams.mAsyncViewHost).isTrue();
@@ -1103,19 +843,7 @@
         taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
         final RelayoutParams relayoutParams = new RelayoutParams();
 
-        DesktopModeWindowDecoration.updateRelayoutParams(
-                relayoutParams,
-                mTestableContext,
-                taskInfo,
-                mMockSplitScreenController,
-                /* applyStartTransactionOnDraw= */ true,
-                /* shouldSetTaskPositionAndCrop= */ false,
-                /* isStatusBarVisible= */ true,
-                /* isKeyguardVisibleAndOccluded= */ false,
-                /* inFullImmersiveMode= */ false,
-                new InsetsState(),
-                /* hasGlobalFocus= */ true,
-                mExclusionRegion);
+        updateRelayoutParams(relayoutParams, taskInfo);
 
         // App Headers must be rendered in sync with the task animation, so it cannot be delayed.
         assertThat(relayoutParams.mAsyncViewHost).isFalse();
@@ -1734,6 +1462,23 @@
                 R.dimen.rounded_corner_radius_bottom, fillValue);
     }
 
+    private void updateRelayoutParams(
+            RelayoutParams relayoutParams, ActivityManager.RunningTaskInfo taskInfo) {
+        DesktopModeWindowDecoration.updateRelayoutParams(
+                relayoutParams,
+                mTestableContext,
+                taskInfo,
+                mMockSplitScreenController,
+                DEFAULT_APPLY_START_TRANSACTION_ON_DRAW,
+                DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP,
+                DEFAULT_IS_STATUSBAR_VISIBLE,
+                DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED,
+                DEFAULT_IS_IN_FULL_IMMERSIVE_MODE,
+                new InsetsState(),
+                DEFAULT_HAS_GLOBAL_FOCUS,
+                mExclusionRegion);
+    }
+
     private DesktopModeWindowDecoration createWindowDecoration(
             ActivityManager.RunningTaskInfo taskInfo, @Nullable Uri capturedLink,
             @Nullable Uri webUri, @Nullable Uri sessionTransferUri, @Nullable Uri genericLink) {
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 1bc15d7..cc4a29b 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -199,6 +199,7 @@
         // This is to suppress warnings/errors from gtest
         "-Wno-unnamed-type-template-args",
     ],
+    require_root: true,
     srcs: [
         // Helpers/infra for testing.
         "tests/CommonHelpers.cpp",
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index e618245..5955915 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -1420,18 +1420,20 @@
 Mutex AssetManager::SharedZip::gLock;
 DefaultKeyedVector<String8, wp<AssetManager::SharedZip> > AssetManager::SharedZip::gOpen;
 
-AssetManager::SharedZip::SharedZip(const String8& path, time_t modWhen)
-    : mPath(path), mZipFile(NULL), mModWhen(modWhen),
-      mResourceTableAsset(NULL), mResourceTable(NULL)
-{
-    if (kIsDebug) {
-        ALOGI("Creating SharedZip %p %s\n", this, mPath.c_str());
-    }
-    ALOGV("+++ opening zip '%s'\n", mPath.c_str());
-    mZipFile = ZipFileRO::open(mPath.c_str());
-    if (mZipFile == NULL) {
-        ALOGD("failed to open Zip archive '%s'\n", mPath.c_str());
-    }
+AssetManager::SharedZip::SharedZip(const String8& path, ModDate modWhen)
+    : mPath(path),
+      mZipFile(NULL),
+      mModWhen(modWhen),
+      mResourceTableAsset(NULL),
+      mResourceTable(NULL) {
+  if (kIsDebug) {
+    ALOGI("Creating SharedZip %p %s\n", this, mPath.c_str());
+  }
+  ALOGV("+++ opening zip '%s'\n", mPath.c_str());
+  mZipFile = ZipFileRO::open(mPath.c_str());
+  if (mZipFile == NULL) {
+    ALOGD("failed to open Zip archive '%s'\n", mPath.c_str());
+  }
 }
 
 AssetManager::SharedZip::SharedZip(int fd, const String8& path)
@@ -1453,7 +1455,7 @@
         bool createIfNotPresent)
 {
     AutoMutex _l(gLock);
-    time_t modWhen = getFileModDate(path.c_str());
+    auto modWhen = getFileModDate(path.c_str());
     sp<SharedZip> zip = gOpen.valueFor(path).promote();
     if (zip != NULL && zip->mModWhen == modWhen) {
         return zip;
@@ -1520,8 +1522,8 @@
 
 bool AssetManager::SharedZip::isUpToDate()
 {
-    time_t modWhen = getFileModDate(mPath.c_str());
-    return mModWhen == modWhen;
+  auto modWhen = getFileModDate(mPath.c_str());
+  return mModWhen == modWhen;
 }
 
 void AssetManager::SharedZip::addOverlay(const asset_path& ap)
diff --git a/libs/androidfw/TypeWrappers.cpp b/libs/androidfw/TypeWrappers.cpp
index 70d14a1..9704634 100644
--- a/libs/androidfw/TypeWrappers.cpp
+++ b/libs/androidfw/TypeWrappers.cpp
@@ -16,8 +16,6 @@
 
 #include <androidfw/TypeWrappers.h>
 
-#include <algorithm>
-
 namespace android {
 
 TypeVariant::TypeVariant(const ResTable_type* data) : data(data), mLength(dtohl(data->entryCount)) {
@@ -31,30 +29,44 @@
             ALOGE("Type's entry indices extend beyond its boundaries");
             mLength = 0;
         } else {
-          mLength = ResTable_sparseTypeEntry{entryIndices[entryCount - 1]}.idx + 1;
+          mLength = dtohs(ResTable_sparseTypeEntry{entryIndices[entryCount - 1]}.idx) + 1;
         }
     }
 }
 
 TypeVariant::iterator& TypeVariant::iterator::operator++() {
-    mIndex++;
+    ++mIndex;
     if (mIndex > mTypeVariant->mLength) {
         mIndex = mTypeVariant->mLength;
     }
+
+    const ResTable_type* type = mTypeVariant->data;
+    if ((type->flags & ResTable_type::FLAG_SPARSE) == 0) {
+      return *this;
+    }
+
+    // Need to adjust |mSparseIndex| as well if we've passed its current element.
+    const uint32_t entryCount = dtohl(type->entryCount);
+    const auto entryIndices = reinterpret_cast<const uint32_t*>(
+        reinterpret_cast<uintptr_t>(type) + dtohs(type->header.headerSize));
+    if (mSparseIndex >= entryCount) {
+      return *this; // done
+    }
+    const auto element = (const ResTable_sparseTypeEntry*)(entryIndices + mSparseIndex);
+    if (mIndex > dtohs(element->idx)) {
+      ++mSparseIndex;
+    }
+
     return *this;
 }
 
-static bool keyCompare(uint32_t entry, uint16_t index) {
-  return dtohs(ResTable_sparseTypeEntry{entry}.idx) < index;
-}
-
 const ResTable_entry* TypeVariant::iterator::operator*() const {
-    const ResTable_type* type = mTypeVariant->data;
     if (mIndex >= mTypeVariant->mLength) {
-        return NULL;
+        return nullptr;
     }
 
-    const uint32_t entryCount = dtohl(mTypeVariant->data->entryCount);
+    const ResTable_type* type = mTypeVariant->data;
+    const uint32_t entryCount = dtohl(type->entryCount);
     const uintptr_t containerEnd = reinterpret_cast<uintptr_t>(type)
             + dtohl(type->header.size);
     const uint32_t* const entryIndices = reinterpret_cast<const uint32_t*>(
@@ -63,18 +75,19 @@
                                     sizeof(uint16_t) : sizeof(uint32_t);
     if (reinterpret_cast<uintptr_t>(entryIndices) + (indexSize * entryCount) > containerEnd) {
         ALOGE("Type's entry indices extend beyond its boundaries");
-        return NULL;
+        return nullptr;
     }
 
     uint32_t entryOffset;
     if (type->flags & ResTable_type::FLAG_SPARSE) {
-      auto iter = std::lower_bound(entryIndices, entryIndices + entryCount, mIndex, keyCompare);
-      if (iter == entryIndices + entryCount
-              || dtohs(ResTable_sparseTypeEntry{*iter}.idx) != mIndex) {
-        return NULL;
+      if (mSparseIndex >= entryCount) {
+        return nullptr;
       }
-
-      entryOffset = static_cast<uint32_t>(dtohs(ResTable_sparseTypeEntry{*iter}.offset)) * 4u;
+      const auto element = (const ResTable_sparseTypeEntry*)(entryIndices + mSparseIndex);
+      if (dtohs(element->idx) != mIndex) {
+        return nullptr;
+      }
+      entryOffset = static_cast<uint32_t>(dtohs(element->offset)) * 4u;
     } else if (type->flags & ResTable_type::FLAG_OFFSET16) {
       auto entryIndices16 = reinterpret_cast<const uint16_t*>(entryIndices);
       entryOffset = offset_from16(entryIndices16[mIndex]);
@@ -83,25 +96,25 @@
     }
 
     if (entryOffset == ResTable_type::NO_ENTRY) {
-        return NULL;
+        return nullptr;
     }
 
     if ((entryOffset & 0x3) != 0) {
         ALOGE("Index %u points to entry with unaligned offset 0x%08x", mIndex, entryOffset);
-        return NULL;
+        return nullptr;
     }
 
     const ResTable_entry* entry = reinterpret_cast<const ResTable_entry*>(
             reinterpret_cast<uintptr_t>(type) + dtohl(type->entriesStart) + entryOffset);
     if (reinterpret_cast<uintptr_t>(entry) > containerEnd - sizeof(*entry)) {
         ALOGE("Entry offset at index %u points outside the Type's boundaries", mIndex);
-        return NULL;
+        return nullptr;
     } else if (reinterpret_cast<uintptr_t>(entry) + entry->size() > containerEnd) {
         ALOGE("Entry at index %u extends beyond Type's boundaries", mIndex);
-        return NULL;
+        return nullptr;
     } else if (entry->size() < sizeof(*entry)) {
         ALOGE("Entry at index %u is too small (%zu)", mIndex, entry->size());
-        return NULL;
+        return nullptr;
     }
     return entry;
 }
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index ce0985b..376c881 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -280,21 +280,21 @@
         ~SharedZip();
 
     private:
-        SharedZip(const String8& path, time_t modWhen);
-        SharedZip(int fd, const String8& path);
-        SharedZip(); // <-- not implemented
+     SharedZip(const String8& path, ModDate modWhen);
+     SharedZip(int fd, const String8& path);
+     SharedZip();  // <-- not implemented
 
-        String8 mPath;
-        ZipFileRO* mZipFile;
-        time_t mModWhen;
+     String8 mPath;
+     ZipFileRO* mZipFile;
+     ModDate mModWhen;
 
-        Asset* mResourceTableAsset;
-        ResTable* mResourceTable;
+     Asset* mResourceTableAsset;
+     ResTable* mResourceTable;
 
-        Vector<asset_path> mOverlays;
+     Vector<asset_path> mOverlays;
 
-        static Mutex gLock;
-        static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
+     static Mutex gLock;
+     static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
     };
 
     /*
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index e213fbd..ac75eb3 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -25,8 +25,9 @@
 #include "android-base/macros.h"
 #include "android-base/unique_fd.h"
 #include "androidfw/ConfigDescription.h"
-#include "androidfw/StringPiece.h"
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+#include "androidfw/misc.h"
 #include "utils/ByteOrder.h"
 
 namespace android {
@@ -213,7 +214,7 @@
   android::base::unique_fd idmap_fd_;
   std::string_view overlay_apk_path_;
   std::string_view target_apk_path_;
-  time_t idmap_last_mod_time_;
+  ModDate idmap_last_mod_time_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedIdmap);
diff --git a/libs/androidfw/include/androidfw/TypeWrappers.h b/libs/androidfw/include/androidfw/TypeWrappers.h
index fb2fad6..db641b7 100644
--- a/libs/androidfw/include/androidfw/TypeWrappers.h
+++ b/libs/androidfw/include/androidfw/TypeWrappers.h
@@ -27,24 +27,14 @@
 
     class iterator {
     public:
-        iterator& operator=(const iterator& rhs) {
-            mTypeVariant = rhs.mTypeVariant;
-            mIndex = rhs.mIndex;
-            return *this;
-        }
-
         bool operator==(const iterator& rhs) const {
             return mTypeVariant == rhs.mTypeVariant && mIndex == rhs.mIndex;
         }
 
-        bool operator!=(const iterator& rhs) const {
-            return mTypeVariant != rhs.mTypeVariant || mIndex != rhs.mIndex;
-        }
-
         iterator operator++(int) {
-            uint32_t prevIndex = mIndex;
+            iterator prev = *this;
             operator++();
-            return iterator(mTypeVariant, prevIndex);
+            return prev;
         }
 
         const ResTable_entry* operator->() const {
@@ -60,18 +50,26 @@
 
     private:
         friend struct TypeVariant;
-        iterator(const TypeVariant* tv, uint32_t index)
-            : mTypeVariant(tv), mIndex(index) {}
+
+        enum class Kind { Begin, End };
+        iterator(const TypeVariant* tv, Kind kind)
+            : mTypeVariant(tv) {
+          mSparseIndex = mIndex = kind == Kind::Begin ? 0 : tv->mLength;
+          // mSparseIndex here is technically past the number of sparse entries, but it is still
+          // ok as it is enough to infer that this is the end iterator.
+        }
+
         const TypeVariant* mTypeVariant;
         uint32_t mIndex;
+        uint32_t mSparseIndex;
     };
 
     iterator beginEntries() const {
-        return iterator(this, 0);
+        return iterator(this, iterator::Kind::Begin);
     }
 
     iterator endEntries() const {
-        return iterator(this, mLength);
+        return iterator(this, iterator::Kind::End);
     }
 
     const ResTable_type* data;
diff --git a/libs/androidfw/include/androidfw/misc.h b/libs/androidfw/include/androidfw/misc.h
index 077609d..c9ba8a0 100644
--- a/libs/androidfw/include/androidfw/misc.h
+++ b/libs/androidfw/include/androidfw/misc.h
@@ -13,14 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
-#include <sys/types.h>
+#include <time.h>
 
 //
 // Handy utility functions and portability code.
 //
-#ifndef _LIBS_ANDROID_FW_MISC_H
-#define _LIBS_ANDROID_FW_MISC_H
 
 namespace android {
 
@@ -41,15 +40,35 @@
 } FileType;
 /* get the file's type; follows symlinks */
 FileType getFileType(const char* fileName);
-/* get the file's modification date; returns -1 w/errno set on failure */
-time_t getFileModDate(const char* fileName);
+
+// MinGW doesn't support nanosecond resolution in stat() modification time, and given
+// that it only matters on the device it's ok to keep it at a seconds level there.
+#ifdef _WIN32
+using ModDate = time_t;
+inline constexpr ModDate kInvalidModDate = ModDate(-1);
+inline constexpr unsigned long long kModDateResolutionNs = 1ull * 1000 * 1000 * 1000;
+inline time_t toTimeT(ModDate m) {
+  return m;
+}
+#else
+using ModDate = timespec;
+inline constexpr ModDate kInvalidModDate = {-1, -1};
+inline constexpr unsigned long long kModDateResolutionNs = 1;
+inline time_t toTimeT(ModDate m) {
+  return m.tv_sec;
+}
+#endif
+
+/* get the file's modification date; returns kInvalidModDate w/errno set on failure */
+ModDate getFileModDate(const char* fileName);
 /* same, but also returns -1 if the file has already been deleted */
-time_t getFileModDate(int fd);
+ModDate getFileModDate(int fd);
 
 // Check if |path| or |fd| resides on a readonly filesystem.
 bool isReadonlyFilesystem(const char* path);
 bool isReadonlyFilesystem(int fd);
 
-}; // namespace android
+}  // namespace android
 
-#endif // _LIBS_ANDROID_FW_MISC_H
+// Whoever uses getFileModDate() will need this as well
+bool operator==(const timespec& l, const timespec& r);
diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp
index 93dcaf5..32f3624 100644
--- a/libs/androidfw/misc.cpp
+++ b/libs/androidfw/misc.cpp
@@ -28,11 +28,13 @@
 #include <sys/vfs.h>
 #endif  // __linux__
 
-#include <cstring>
-#include <cstdio>
 #include <errno.h>
 #include <sys/stat.h>
 
+#include <cstdio>
+#include <cstring>
+#include <tuple>
+
 namespace android {
 
 /*
@@ -73,27 +75,34 @@
     }
 }
 
-/*
- * Get a file's modification date.
- */
-time_t getFileModDate(const char* fileName) {
-    struct stat sb;
-    if (stat(fileName, &sb) < 0) {
-        return (time_t)-1;
-    }
-    return sb.st_mtime;
+static ModDate getModDate(const struct stat& st) {
+#ifdef _WIN32
+  return st.st_mtime;
+#elif defined(__APPLE__)
+  return st.st_mtimespec;
+#else
+  return st.st_mtim;
+#endif
 }
 
-time_t getFileModDate(int fd) {
-    struct stat sb;
-    if (fstat(fd, &sb) < 0) {
-        return (time_t)-1;
-    }
-    if (sb.st_nlink <= 0) {
-        errno = ENOENT;
-        return (time_t)-1;
-    }
-    return sb.st_mtime;
+ModDate getFileModDate(const char* fileName) {
+  struct stat sb;
+  if (stat(fileName, &sb) < 0) {
+    return kInvalidModDate;
+  }
+  return getModDate(sb);
+}
+
+ModDate getFileModDate(int fd) {
+  struct stat sb;
+  if (fstat(fd, &sb) < 0) {
+    return kInvalidModDate;
+  }
+  if (sb.st_nlink <= 0) {
+    errno = ENOENT;
+    return kInvalidModDate;
+  }
+  return getModDate(sb);
 }
 
 #ifndef __linux__
@@ -124,4 +133,8 @@
 }
 #endif  // __linux__
 
-}; // namespace android
+}  // namespace android
+
+bool operator==(const timespec& l, const timespec& r) {
+  return std::tie(l.tv_sec, l.tv_nsec) == std::tie(r.tv_sec, l.tv_nsec);
+}
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 60aa7d8..cb2e56f 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <chrono>
+#include <thread>
+
 #include "android-base/file.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/AssetManager2.h"
@@ -27,6 +30,7 @@
 #include "data/overlayable/R.h"
 #include "data/system/R.h"
 
+using namespace std::chrono_literals;
 using ::testing::NotNull;
 
 namespace overlay = com::android::overlay;
@@ -218,10 +222,13 @@
 
   unlink(temp_file.path);
   ASSERT_FALSE(apk_assets->IsUpToDate());
-  sleep(2);
+
+  const auto sleep_duration =
+      std::chrono::nanoseconds(std::max(kModDateResolutionNs, 1'000'000ull));
+  std::this_thread::sleep_for(sleep_duration);
 
   base::WriteStringToFile("hello", temp_file.path);
-  sleep(2);
+  std::this_thread::sleep_for(sleep_duration);
 
   ASSERT_FALSE(apk_assets->IsUpToDate());
 }
diff --git a/libs/androidfw/tests/TypeWrappers_test.cpp b/libs/androidfw/tests/TypeWrappers_test.cpp
index ed30904..d66e058 100644
--- a/libs/androidfw/tests/TypeWrappers_test.cpp
+++ b/libs/androidfw/tests/TypeWrappers_test.cpp
@@ -14,28 +14,42 @@
  * limitations under the License.
  */
 
-#include <algorithm>
 #include <androidfw/ResourceTypes.h>
 #include <androidfw/TypeWrappers.h>
-#include <utils/String8.h>
+#include <androidfw/Util.h>
+
+#include <optional>
+#include <vector>
 
 #include <gtest/gtest.h>
 
 namespace android {
 
-// create a ResTable_type in memory with a vector of Res_value*
-static ResTable_type* createTypeTable(std::vector<Res_value*>& values,
-                             bool compact_entry = false,
-                             bool short_offsets = false)
+using ResValueVector = std::vector<std::optional<Res_value>>;
+
+// create a ResTable_type in memory
+static util::unique_cptr<ResTable_type> createTypeTable(
+    const ResValueVector& in_values, bool compact_entry, bool short_offsets, bool sparse)
 {
+    ResValueVector sparse_values;
+    if (sparse) {
+      std::ranges::copy_if(in_values, std::back_inserter(sparse_values),
+                           [](auto&& v) { return v.has_value(); });
+    }
+    const ResValueVector& values = sparse ? sparse_values : in_values;
+
     ResTable_type t{};
     t.header.type = RES_TABLE_TYPE_TYPE;
     t.header.headerSize = sizeof(t);
     t.header.size = sizeof(t);
     t.id = 1;
-    t.flags = short_offsets ? ResTable_type::FLAG_OFFSET16 : 0;
+    t.flags = sparse
+                  ? ResTable_type::FLAG_SPARSE
+                  : short_offsets ? ResTable_type::FLAG_OFFSET16 : 0;
 
-    t.header.size += values.size() * (short_offsets ? sizeof(uint16_t) : sizeof(uint32_t));
+    t.header.size += values.size() *
+                     (sparse ? sizeof(ResTable_sparseTypeEntry) :
+                         short_offsets ? sizeof(uint16_t) : sizeof(uint32_t));
     t.entriesStart = t.header.size;
     t.entryCount = values.size();
 
@@ -53,9 +67,18 @@
     memcpy(p_header, &t, sizeof(t));
 
     size_t i = 0, entry_offset = 0;
-    uint32_t k = 0;
-    for (auto const& v : values) {
-        if (short_offsets) {
+    uint32_t sparse_index = 0;
+
+    for (auto const& v : in_values) {
+        if (sparse) {
+            if (!v) {
+                ++i;
+                continue;
+            }
+            const auto p = reinterpret_cast<ResTable_sparseTypeEntry*>(p_offsets) + sparse_index++;
+            p->idx = i;
+            p->offset = (entry_offset >> 2) & 0xffffu;
+        } else if (short_offsets) {
             uint16_t *p = reinterpret_cast<uint16_t *>(p_offsets) + i;
             *p = v ? (entry_offset >> 2) & 0xffffu : 0xffffu;
         } else {
@@ -83,62 +106,92 @@
         }
         i++;
     }
-    return reinterpret_cast<ResTable_type*>(data);
+    return util::unique_cptr<ResTable_type>{reinterpret_cast<ResTable_type*>(data)};
 }
 
 TEST(TypeVariantIteratorTest, shouldIterateOverTypeWithoutErrors) {
-    std::vector<Res_value *> values;
+    ResValueVector values;
 
-    Res_value *v1 = new Res_value{};
-    values.push_back(v1);
-
-    values.push_back(nullptr);
-
-    Res_value *v2 = new Res_value{};
-    values.push_back(v2);
-
-    Res_value *v3 = new Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x12345678};
-    values.push_back(v3);
+    values.push_back(std::nullopt);
+    values.push_back(Res_value{});
+    values.push_back(std::nullopt);
+    values.push_back(Res_value{});
+    values.push_back(Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x12345678});
+    values.push_back(std::nullopt);
+    values.push_back(std::nullopt);
+    values.push_back(std::nullopt);
+    values.push_back(Res_value{ sizeof(Res_value), 0, Res_value::TYPE_STRING, 0x87654321});
 
     // test for combinations of compact_entry and short_offsets
-    for (size_t i = 0; i < 4; i++) {
-        bool compact_entry = i & 0x1, short_offsets = i & 0x2;
-        ResTable_type* data = createTypeTable(values, compact_entry, short_offsets);
-        TypeVariant v(data);
+    for (size_t i = 0; i < 8; i++) {
+        bool compact_entry = i & 0x1, short_offsets = i & 0x2, sparse = i & 0x4;
+        auto data = createTypeTable(values, compact_entry, short_offsets, sparse);
+        TypeVariant v(data.get());
 
         TypeVariant::iterator iter = v.beginEntries();
         ASSERT_EQ(uint32_t(0), iter.index());
-        ASSERT_TRUE(NULL != *iter);
-        ASSERT_EQ(uint32_t(0), iter->key());
+        ASSERT_TRUE(NULL == *iter);
         ASSERT_NE(v.endEntries(), iter);
 
-        iter++;
+        ++iter;
 
         ASSERT_EQ(uint32_t(1), iter.index());
-        ASSERT_TRUE(NULL == *iter);
+        ASSERT_TRUE(NULL != *iter);
+        ASSERT_EQ(uint32_t(1), iter->key());
         ASSERT_NE(v.endEntries(), iter);
 
         iter++;
 
         ASSERT_EQ(uint32_t(2), iter.index());
+        ASSERT_TRUE(NULL == *iter);
+        ASSERT_NE(v.endEntries(), iter);
+
+        ++iter;
+
+        ASSERT_EQ(uint32_t(3), iter.index());
         ASSERT_TRUE(NULL != *iter);
-        ASSERT_EQ(uint32_t(2), iter->key());
+        ASSERT_EQ(uint32_t(3), iter->key());
         ASSERT_NE(v.endEntries(), iter);
 
         iter++;
 
-        ASSERT_EQ(uint32_t(3), iter.index());
+        ASSERT_EQ(uint32_t(4), iter.index());
         ASSERT_TRUE(NULL != *iter);
         ASSERT_EQ(iter->is_compact(), compact_entry);
-        ASSERT_EQ(uint32_t(3), iter->key());
+        ASSERT_EQ(uint32_t(4), iter->key());
         ASSERT_EQ(uint32_t(0x12345678), iter->value().data);
         ASSERT_EQ(Res_value::TYPE_STRING, iter->value().dataType);
 
+        ++iter;
+
+        ASSERT_EQ(uint32_t(5), iter.index());
+        ASSERT_TRUE(NULL == *iter);
+        ASSERT_NE(v.endEntries(), iter);
+
+        ++iter;
+
+        ASSERT_EQ(uint32_t(6), iter.index());
+        ASSERT_TRUE(NULL == *iter);
+        ASSERT_NE(v.endEntries(), iter);
+
+        ++iter;
+
+        ASSERT_EQ(uint32_t(7), iter.index());
+        ASSERT_TRUE(NULL == *iter);
+        ASSERT_NE(v.endEntries(), iter);
+
         iter++;
 
-        ASSERT_EQ(v.endEntries(), iter);
+        ASSERT_EQ(uint32_t(8), iter.index());
+        ASSERT_TRUE(NULL != *iter);
+        ASSERT_EQ(iter->is_compact(), compact_entry);
+        ASSERT_EQ(uint32_t(8), iter->key());
+        ASSERT_EQ(uint32_t(0x87654321), iter->value().data);
+        ASSERT_EQ(Res_value::TYPE_STRING, iter->value().dataType);
 
-        free(data);
+        ++iter;
+
+        ASSERT_EQ(v.endEntries(), iter);
     }
 }
 
diff --git a/libs/dream/lowlight/res/values/config.xml b/libs/dream/lowlight/res/values/config.xml
index 78fefbf..2b8fe02 100644
--- a/libs/dream/lowlight/res/values/config.xml
+++ b/libs/dream/lowlight/res/values/config.xml
@@ -15,8 +15,6 @@
   ~ limitations under the License.
   -->
 <resources>
-    <!-- The dream component used when the device is low light environment. -->
-    <string translatable="false" name="config_lowLightDreamComponent"/>
     <!-- The max number of milliseconds to wait for the low light transition before setting
     the system dream component -->
     <integer name="config_lowLightTransitionTimeoutMs">2000</integer>
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamComponent.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamComponent.kt
new file mode 100644
index 0000000..2314f94
--- /dev/null
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamComponent.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.dream.lowlight.dagger
+
+import android.app.DreamManager
+import android.content.ComponentName
+import dagger.BindsInstance
+import dagger.Subcomponent
+import javax.inject.Named
+
+@Subcomponent(modules = [LowLightDreamModule::class])
+interface LowLightDreamComponent {
+    @Subcomponent.Factory
+    interface Factory {
+        fun create(@BindsInstance dreamManager: DreamManager,
+                   @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
+                   @BindsInstance lowLightDreamComponent: ComponentName?
+        ): LowLightDreamComponent
+    }
+}
\ No newline at end of file
diff --git a/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.kt b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.kt
index dd274bd..0161eef 100644
--- a/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.kt
+++ b/libs/dream/lowlight/src/com/android/dream/lowlight/dagger/LowLightDreamModule.kt
@@ -15,8 +15,6 @@
  */
 package com.android.dream.lowlight.dagger
 
-import android.app.DreamManager
-import android.content.ComponentName
 import android.content.Context
 import com.android.dream.lowlight.R
 import com.android.dream.lowlight.dagger.qualifiers.Application
@@ -35,30 +33,6 @@
  */
 @Module
 object LowLightDreamModule {
-    /**
-     * Provides dream manager.
-     */
-    @Provides
-    fun providesDreamManager(context: Context): DreamManager {
-        return requireNotNull(context.getSystemService(DreamManager::class.java))
-    }
-
-    /**
-     * Provides the component name of the low light dream, or null if not configured.
-     */
-    @Provides
-    @Named(LOW_LIGHT_DREAM_COMPONENT)
-    fun providesLowLightDreamComponent(context: Context): ComponentName? {
-        val lowLightDreamComponent = context.resources.getString(
-            R.string.config_lowLightDreamComponent
-        )
-        return if (lowLightDreamComponent.isEmpty()) {
-            null
-        } else {
-            ComponentName.unflattenFromString(lowLightDreamComponent)
-        }
-    }
-
     @Provides
     @Named(LOW_LIGHT_TRANSITION_TIMEOUT_MS)
     fun providesLowLightTransitionTimeout(context: Context): Long {
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index 0f458dd..707577d 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -107,6 +107,11 @@
     return toTypeface(faceHandle)->fStyle.weight();
 }
 
+// Critical Native
+static jboolean Typeface_isVariationInstance(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
+    return toTypeface(faceHandle)->fIsVariationInstance;
+}
+
 static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
                                       jlong fallbackPtr, int weight, int italic) {
     ScopedLongArrayRO families(env, familyArray);
@@ -398,6 +403,7 @@
         {"nativeGetReleaseFunc", "()J", (void*)Typeface_getReleaseFunc},
         {"nativeGetStyle", "(J)I", (void*)Typeface_getStyle},
         {"nativeGetWeight", "(J)I", (void*)Typeface_getWeight},
+        {"nativeIsVariationInstance", "(J)Z", (void*)Typeface_isVariationInstance},
         {"nativeCreateFromArray", "([JJII)J", (void*)Typeface_createFromArray},
         {"nativeSetDefault", "(J)V", (void*)Typeface_setDefault},
         {"nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes},
diff --git a/libs/protoutil/Android.bp b/libs/protoutil/Android.bp
index 8af4b7e..4fecf4d 100644
--- a/libs/protoutil/Android.bp
+++ b/libs/protoutil/Android.bp
@@ -59,7 +59,6 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.os.statsd",
-        "test_com.android.os.statsd",
         "com.android.uprobestats",
     ],
 }
diff --git a/location/api/system-current.txt b/location/api/system-current.txt
index ba42241..eb19ba8 100644
--- a/location/api/system-current.txt
+++ b/location/api/system-current.txt
@@ -1,6 +1,29 @@
 // Signature format: 2.0
 package android.location {
 
+  @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class AuxiliaryInformation implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.location.GnssSignalType> getAvailableSignalTypes();
+    method @IntRange(from=0xfffffff9, to=6) public int getFrequencyChannelNumber();
+    method public int getSatType();
+    method @IntRange(from=1) public int getSvid();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int BDS_B1C_ORBIT_TYPE_GEO = 1; // 0x1
+    field public static final int BDS_B1C_ORBIT_TYPE_IGSO = 2; // 0x2
+    field public static final int BDS_B1C_ORBIT_TYPE_MEO = 3; // 0x3
+    field public static final int BDS_B1C_ORBIT_TYPE_UNDEFINED = 0; // 0x0
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.AuxiliaryInformation> CREATOR;
+  }
+
+  public static final class AuxiliaryInformation.Builder {
+    ctor public AuxiliaryInformation.Builder();
+    method @NonNull public android.location.AuxiliaryInformation build();
+    method @NonNull public android.location.AuxiliaryInformation.Builder setAvailableSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
+    method @NonNull public android.location.AuxiliaryInformation.Builder setFrequencyChannelNumber(@IntRange(from=0xfffffff9, to=6) int);
+    method @NonNull public android.location.AuxiliaryInformation.Builder setSatType(int);
+    method @NonNull public android.location.AuxiliaryInformation.Builder setSvid(@IntRange(from=1) int);
+  }
+
   public abstract class BatchedLocationCallback {
     ctor public BatchedLocationCallback();
     method public void onLocationBatch(java.util.List<android.location.Location>);
@@ -9,6 +32,7 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class BeidouAssistance implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.location.GnssAlmanac getAlmanac();
+    method @Nullable public android.location.AuxiliaryInformation getAuxiliaryInformation();
     method @Nullable public android.location.KlobucharIonosphericModel getIonosphericModel();
     method @Nullable public android.location.LeapSecondsModel getLeapSecondsModel();
     method @NonNull public java.util.List<android.location.RealTimeIntegrityModel> getRealTimeIntegrityModels();
@@ -24,22 +48,23 @@
     ctor public BeidouAssistance.Builder();
     method @NonNull public android.location.BeidouAssistance build();
     method @NonNull public android.location.BeidouAssistance.Builder setAlmanac(@Nullable android.location.GnssAlmanac);
+    method @NonNull public android.location.BeidouAssistance.Builder setAuxiliaryInformation(@Nullable android.location.AuxiliaryInformation);
     method @NonNull public android.location.BeidouAssistance.Builder setIonosphericModel(@Nullable android.location.KlobucharIonosphericModel);
     method @NonNull public android.location.BeidouAssistance.Builder setLeapSecondsModel(@Nullable android.location.LeapSecondsModel);
-    method @NonNull public android.location.BeidouAssistance.Builder setRealTimeIntegrityModels(@Nullable java.util.List<android.location.RealTimeIntegrityModel>);
-    method @NonNull public android.location.BeidouAssistance.Builder setSatelliteCorrections(@Nullable java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
-    method @NonNull public android.location.BeidouAssistance.Builder setSatelliteEphemeris(@Nullable java.util.List<android.location.BeidouSatelliteEphemeris>);
-    method @NonNull public android.location.BeidouAssistance.Builder setTimeModels(@Nullable java.util.List<android.location.TimeModel>);
+    method @NonNull public android.location.BeidouAssistance.Builder setRealTimeIntegrityModels(@NonNull java.util.List<android.location.RealTimeIntegrityModel>);
+    method @NonNull public android.location.BeidouAssistance.Builder setSatelliteCorrections(@NonNull java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
+    method @NonNull public android.location.BeidouAssistance.Builder setSatelliteEphemeris(@NonNull java.util.List<android.location.BeidouSatelliteEphemeris>);
+    method @NonNull public android.location.BeidouAssistance.Builder setTimeModels(@NonNull java.util.List<android.location.TimeModel>);
     method @NonNull public android.location.BeidouAssistance.Builder setUtcModel(@Nullable android.location.UtcModel);
   }
 
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class BeidouSatelliteEphemeris implements android.os.Parcelable {
     method public int describeContents();
-    method @IntRange(from=1, to=63) public int getPrn();
     method @NonNull public android.location.BeidouSatelliteEphemeris.BeidouSatelliteClockModel getSatelliteClockModel();
     method @NonNull public android.location.BeidouSatelliteEphemeris.BeidouSatelliteEphemerisTime getSatelliteEphemerisTime();
     method @NonNull public android.location.BeidouSatelliteEphemeris.BeidouSatelliteHealth getSatelliteHealth();
     method @NonNull public android.location.KeplerianOrbitModel getSatelliteOrbitModel();
+    method @IntRange(from=1, to=63) public int getSvid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.BeidouSatelliteEphemeris> CREATOR;
   }
@@ -104,11 +129,11 @@
   public static final class BeidouSatelliteEphemeris.Builder {
     ctor public BeidouSatelliteEphemeris.Builder();
     method @NonNull public android.location.BeidouSatelliteEphemeris build();
-    method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setPrn(int);
     method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setSatelliteClockModel(@NonNull android.location.BeidouSatelliteEphemeris.BeidouSatelliteClockModel);
     method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setSatelliteEphemerisTime(@NonNull android.location.BeidouSatelliteEphemeris.BeidouSatelliteEphemerisTime);
     method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setSatelliteHealth(@NonNull android.location.BeidouSatelliteEphemeris.BeidouSatelliteHealth);
     method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setSatelliteOrbitModel(@NonNull android.location.KeplerianOrbitModel);
+    method @NonNull public android.location.BeidouSatelliteEphemeris.Builder setSvid(int);
   }
 
   public final class CorrelationVector implements android.os.Parcelable {
@@ -151,6 +176,7 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GalileoAssistance implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.location.GnssAlmanac getAlmanac();
+    method @Nullable public android.location.AuxiliaryInformation getAuxiliaryInformation();
     method @Nullable public android.location.KlobucharIonosphericModel getIonosphericModel();
     method @Nullable public android.location.LeapSecondsModel getLeapSecondsModel();
     method @NonNull public java.util.List<android.location.RealTimeIntegrityModel> getRealTimeIntegrityModels();
@@ -166,12 +192,13 @@
     ctor public GalileoAssistance.Builder();
     method @NonNull public android.location.GalileoAssistance build();
     method @NonNull public android.location.GalileoAssistance.Builder setAlmanac(@Nullable android.location.GnssAlmanac);
+    method @NonNull public android.location.GalileoAssistance.Builder setAuxiliaryInformation(@Nullable android.location.AuxiliaryInformation);
     method @NonNull public android.location.GalileoAssistance.Builder setIonosphericModel(@Nullable android.location.KlobucharIonosphericModel);
     method @NonNull public android.location.GalileoAssistance.Builder setLeapSecondsModel(@Nullable android.location.LeapSecondsModel);
-    method @NonNull public android.location.GalileoAssistance.Builder setRealTimeIntegrityModels(@Nullable java.util.List<android.location.RealTimeIntegrityModel>);
-    method @NonNull public android.location.GalileoAssistance.Builder setSatelliteCorrections(@Nullable java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
-    method @NonNull public android.location.GalileoAssistance.Builder setSatelliteEphemeris(@Nullable java.util.List<android.location.GalileoSatelliteEphemeris>);
-    method @NonNull public android.location.GalileoAssistance.Builder setTimeModels(@Nullable java.util.List<android.location.TimeModel>);
+    method @NonNull public android.location.GalileoAssistance.Builder setRealTimeIntegrityModels(@NonNull java.util.List<android.location.RealTimeIntegrityModel>);
+    method @NonNull public android.location.GalileoAssistance.Builder setSatelliteCorrections(@NonNull java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
+    method @NonNull public android.location.GalileoAssistance.Builder setSatelliteEphemeris(@NonNull java.util.List<android.location.GalileoSatelliteEphemeris>);
+    method @NonNull public android.location.GalileoAssistance.Builder setTimeModels(@NonNull java.util.List<android.location.TimeModel>);
     method @NonNull public android.location.GalileoAssistance.Builder setUtcModel(@Nullable android.location.UtcModel);
   }
 
@@ -195,10 +222,10 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GalileoSatelliteEphemeris implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.List<android.location.GalileoSatelliteEphemeris.GalileoSatelliteClockModel> getSatelliteClockModels();
-    method @IntRange(from=1, to=36) public int getSatelliteCodeNumber();
     method @NonNull public android.location.SatelliteEphemerisTime getSatelliteEphemerisTime();
     method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth getSatelliteHealth();
     method @NonNull public android.location.KeplerianOrbitModel getSatelliteOrbitModel();
+    method @IntRange(from=1, to=36) public int getSvid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GalileoSatelliteEphemeris> CREATOR;
   }
@@ -207,10 +234,10 @@
     ctor public GalileoSatelliteEphemeris.Builder();
     method @NonNull public android.location.GalileoSatelliteEphemeris build();
     method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSatelliteClockModels(@NonNull java.util.List<android.location.GalileoSatelliteEphemeris.GalileoSatelliteClockModel>);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSatelliteCodeNumber(@IntRange(from=1, to=36) int);
     method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSatelliteEphemerisTime(@NonNull android.location.SatelliteEphemerisTime);
     method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSatelliteHealth(@NonNull android.location.GalileoSatelliteEphemeris.GalileoSvHealth);
     method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSatelliteOrbitModel(@NonNull android.location.KeplerianOrbitModel);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.Builder setSvid(@IntRange(from=1, to=36) int);
   }
 
   public static final class GalileoSatelliteEphemeris.GalileoSatelliteClockModel implements android.os.Parcelable {
@@ -243,25 +270,31 @@
 
   public static final class GalileoSatelliteEphemeris.GalileoSvHealth implements android.os.Parcelable {
     method public int describeContents();
-    method @IntRange(from=0, to=1) public int getDataValidityStatusE1b();
-    method @IntRange(from=0, to=1) public int getDataValidityStatusE5a();
-    method @IntRange(from=0, to=1) public int getDataValidityStatusE5b();
-    method @IntRange(from=0, to=3) public int getSignalHealthStatusE1b();
-    method @IntRange(from=0, to=3) public int getSignalHealthStatusE5a();
-    method @IntRange(from=0, to=3) public int getSignalHealthStatusE5b();
+    method public int getDataValidityStatusE1b();
+    method public int getDataValidityStatusE5a();
+    method public int getDataValidityStatusE5b();
+    method public int getSignalHealthStatusE1b();
+    method public int getSignalHealthStatusE5a();
+    method public int getSignalHealthStatusE5b();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GalileoSatelliteEphemeris.GalileoSvHealth> CREATOR;
+    field public static final int DATA_STATUS_DATA_VALID = 0; // 0x0
+    field public static final int DATA_STATUS_WORKING_WITHOUT_GUARANTEE = 1; // 0x1
+    field public static final int HEALTH_STATUS_EXTENDED_OPERATION_MODE = 2; // 0x2
+    field public static final int HEALTH_STATUS_IN_TEST = 3; // 0x3
+    field public static final int HEALTH_STATUS_OK = 0; // 0x0
+    field public static final int HEALTH_STATUS_OUT_OF_SERVICE = 1; // 0x1
   }
 
   public static final class GalileoSatelliteEphemeris.GalileoSvHealth.Builder {
     ctor public GalileoSatelliteEphemeris.GalileoSvHealth.Builder();
     method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth build();
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE1b(@IntRange(from=0, to=1) int);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE5a(@IntRange(from=0, to=1) int);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE5b(@IntRange(from=0, to=1) int);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE1b(@IntRange(from=0, to=3) int);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE5a(@IntRange(from=0, to=3) int);
-    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE5b(@IntRange(from=0, to=3) int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE1b(int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE5a(int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setDataValidityStatusE5b(int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE1b(int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE5a(int);
+    method @NonNull public android.location.GalileoSatelliteEphemeris.GalileoSvHealth.Builder setSignalHealthStatusE5b(int);
   }
 
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GlonassAlmanac implements android.os.Parcelable {
@@ -275,17 +308,19 @@
 
   public static final class GlonassAlmanac.GlonassSatelliteAlmanac implements android.os.Parcelable {
     method public int describeContents();
+    method @IntRange(from=1, to=1461) public int getCalendarDayNumber();
     method @FloatRange(from=-0.067F, to=0.067f) public double getDeltaI();
     method @FloatRange(from=-3600.0F, to=3600.0f) public double getDeltaT();
     method @FloatRange(from=-0.004F, to=0.004f) public double getDeltaTDot();
     method @FloatRange(from=0.0f, to=0.03f) public double getEccentricity();
-    method @IntRange(from=0, to=31) public int getFreqChannel();
+    method @IntRange(from=0, to=31) public int getFrequencyChannelNumber();
+    method public int getHealthState();
     method @FloatRange(from=-1.0F, to=1.0f) public double getLambda();
     method @FloatRange(from=-1.0F, to=1.0f) public double getOmega();
     method @IntRange(from=1, to=25) public int getSlotNumber();
-    method @IntRange(from=0, to=1) public int getSvHealth();
     method @FloatRange(from=0.0f, to=44100.0f) public double getTLambda();
     method @FloatRange(from=-0.0019F, to=0.0019f) public double getTau();
+    method public boolean isGlonassM();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GlonassAlmanac.GlonassSatelliteAlmanac> CREATOR;
   }
@@ -293,15 +328,17 @@
   public static final class GlonassAlmanac.GlonassSatelliteAlmanac.Builder {
     ctor public GlonassAlmanac.GlonassSatelliteAlmanac.Builder();
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac build();
+    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setCalendarDayNumber(@IntRange(from=1, to=1461) int);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setDeltaI(@FloatRange(from=-0.067F, to=0.067f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setDeltaT(@FloatRange(from=-3600.0F, to=3600.0f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setDeltaTDot(@FloatRange(from=-0.004F, to=0.004f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setEccentricity(@FloatRange(from=0.0f, to=0.03f) double);
-    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setFreqChannel(@IntRange(from=0, to=31) int);
+    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setFrequencyChannelNumber(@IntRange(from=0, to=31) int);
+    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setGlonassM(boolean);
+    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setHealthState(int);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setLambda(@FloatRange(from=-1.0F, to=1.0f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setOmega(@FloatRange(from=-1.0F, to=1.0f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setSlotNumber(@IntRange(from=1, to=25) int);
-    method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setSvHealth(@IntRange(from=0, to=1) int);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setTLambda(@FloatRange(from=0.0f, to=44100.0f) double);
     method @NonNull public android.location.GlonassAlmanac.GlonassSatelliteAlmanac.Builder setTau(@FloatRange(from=-0.0019F, to=0.0019f) double);
   }
@@ -309,6 +346,7 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GlonassAssistance implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.location.GlonassAlmanac getAlmanac();
+    method @Nullable public android.location.AuxiliaryInformation getAuxiliaryInformation();
     method @NonNull public java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections> getSatelliteCorrections();
     method @NonNull public java.util.List<android.location.GlonassSatelliteEphemeris> getSatelliteEphemeris();
     method @NonNull public java.util.List<android.location.TimeModel> getTimeModels();
@@ -321,9 +359,10 @@
     ctor public GlonassAssistance.Builder();
     method @NonNull public android.location.GlonassAssistance build();
     method @NonNull public android.location.GlonassAssistance.Builder setAlmanac(@Nullable android.location.GlonassAlmanac);
-    method @NonNull public android.location.GlonassAssistance.Builder setSatelliteCorrections(@Nullable java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
-    method @NonNull public android.location.GlonassAssistance.Builder setSatelliteEphemeris(@Nullable java.util.List<android.location.GlonassSatelliteEphemeris>);
-    method @NonNull public android.location.GlonassAssistance.Builder setTimeModels(@Nullable java.util.List<android.location.TimeModel>);
+    method @NonNull public android.location.GlonassAssistance.Builder setAuxiliaryInformation(@Nullable android.location.AuxiliaryInformation);
+    method @NonNull public android.location.GlonassAssistance.Builder setSatelliteCorrections(@NonNull java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
+    method @NonNull public android.location.GlonassAssistance.Builder setSatelliteEphemeris(@NonNull java.util.List<android.location.GlonassSatelliteEphemeris>);
+    method @NonNull public android.location.GlonassAssistance.Builder setTimeModels(@NonNull java.util.List<android.location.TimeModel>);
     method @NonNull public android.location.GlonassAssistance.Builder setUtcModel(@Nullable android.location.UtcModel);
   }
 
@@ -331,12 +370,17 @@
     method public int describeContents();
     method @IntRange(from=0, to=31) public int getAgeInDays();
     method @FloatRange(from=0.0f) public double getFrameTimeSeconds();
-    method @IntRange(from=0, to=1) public int getHealthState();
+    method public int getHealthState();
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel getSatelliteClockModel();
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteOrbitModel getSatelliteOrbitModel();
     method @IntRange(from=1, to=25) public int getSlotNumber();
+    method @IntRange(from=0, to=60) public int getUpdateIntervalMinutes();
+    method public boolean isGlonassM();
+    method public boolean isUpdateIntervalOdd();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GlonassSatelliteEphemeris> CREATOR;
+    field public static final int HEALTH_STATUS_HEALTHY = 0; // 0x0
+    field public static final int HEALTH_STATUS_UNHEALTHY = 1; // 0x1
   }
 
   public static final class GlonassSatelliteEphemeris.Builder {
@@ -344,18 +388,23 @@
     method @NonNull public android.location.GlonassSatelliteEphemeris build();
     method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setAgeInDays(@IntRange(from=0, to=31) int);
     method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setFrameTimeSeconds(@FloatRange(from=0.0f) double);
-    method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setHealthState(@IntRange(from=0, to=1) int);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setGlonassM(boolean);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setHealthState(int);
     method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setSatelliteClockModel(@NonNull android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel);
     method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setSatelliteOrbitModel(@NonNull android.location.GlonassSatelliteEphemeris.GlonassSatelliteOrbitModel);
     method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setSlotNumber(@IntRange(from=1, to=25) int);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setUpdateIntervalMinutes(@IntRange(from=0, to=60) int);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.Builder setUpdateIntervalOdd(boolean);
   }
 
   public static final class GlonassSatelliteEphemeris.GlonassSatelliteClockModel implements android.os.Parcelable {
     method public int describeContents();
     method @FloatRange(from=-0.002F, to=0.002f) public double getClockBias();
     method @FloatRange(from=-9.32E-10F, to=9.32E-10f) public double getFrequencyBias();
-    method @IntRange(from=0xfffffff9, to=6) public int getFrequencyNumber();
+    method @IntRange(from=0xfffffff9, to=6) public int getFrequencyChannelNumber();
+    method @FloatRange(from=-1.4E-8F, to=1.4E-8f) public double getGroupDelayDiffSeconds();
     method @IntRange(from=0) public long getTimeOfClockSeconds();
+    method public boolean isGroupDelayDiffSecondsAvailable();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel> CREATOR;
   }
@@ -365,7 +414,9 @@
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel build();
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setClockBias(@FloatRange(from=-0.002F, to=0.002f) double);
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setFrequencyBias(@FloatRange(from=-9.32E-10F, to=9.32E-10f) double);
-    method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setFrequencyNumber(@IntRange(from=0xfffffff9, to=6) int);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setFrequencyChannelNumber(@IntRange(from=0xfffffff9, to=6) int);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setGroupDelayDiffSeconds(@FloatRange(from=-1.4E-8F, to=1.4E-8f) double);
+    method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setGroupDelayDiffSecondsAvailable(boolean);
     method @NonNull public android.location.GlonassSatelliteEphemeris.GlonassSatelliteClockModel.Builder setTimeOfClockSeconds(@IntRange(from=0) long);
   }
 
@@ -401,10 +452,11 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GnssAlmanac implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public java.util.List<android.location.GnssAlmanac.GnssSatelliteAlmanac> getGnssSatelliteAlmanacs();
-    method @IntRange(from=0) public int getIod();
+    method @IntRange(from=0) public int getIoda();
     method @IntRange(from=0) public long getIssueDateMillis();
     method @IntRange(from=0, to=604800) public int getToaSeconds();
     method @IntRange(from=0) public int getWeekNumber();
+    method public boolean isCompleteAlmanacProvided();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAlmanac> CREATOR;
   }
@@ -412,8 +464,9 @@
   public static final class GnssAlmanac.Builder {
     ctor public GnssAlmanac.Builder();
     method @NonNull public android.location.GnssAlmanac build();
+    method @NonNull public android.location.GnssAlmanac.Builder setCompleteAlmanacProvided(boolean);
     method @NonNull public android.location.GnssAlmanac.Builder setGnssSatelliteAlmanacs(@NonNull java.util.List<android.location.GnssAlmanac.GnssSatelliteAlmanac>);
-    method @NonNull public android.location.GnssAlmanac.Builder setIod(@IntRange(from=0) int);
+    method @NonNull public android.location.GnssAlmanac.Builder setIoda(@IntRange(from=0) int);
     method @NonNull public android.location.GnssAlmanac.Builder setIssueDateMillis(@IntRange(from=0) long);
     method @NonNull public android.location.GnssAlmanac.Builder setToaSeconds(@IntRange(from=0, to=604800) int);
     method @NonNull public android.location.GnssAlmanac.Builder setWeekNumber(@IntRange(from=0) int);
@@ -664,6 +717,7 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GpsAssistance implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.location.GnssAlmanac getAlmanac();
+    method @Nullable public android.location.AuxiliaryInformation getAuxiliaryInformation();
     method @Nullable public android.location.KlobucharIonosphericModel getIonosphericModel();
     method @Nullable public android.location.LeapSecondsModel getLeapSecondsModel();
     method @NonNull public java.util.List<android.location.RealTimeIntegrityModel> getRealTimeIntegrityModels();
@@ -679,12 +733,13 @@
     ctor public GpsAssistance.Builder();
     method @NonNull public android.location.GpsAssistance build();
     method @NonNull public android.location.GpsAssistance.Builder setAlmanac(@Nullable android.location.GnssAlmanac);
+    method @NonNull public android.location.GpsAssistance.Builder setAuxiliaryInformation(@Nullable android.location.AuxiliaryInformation);
     method @NonNull public android.location.GpsAssistance.Builder setIonosphericModel(@Nullable android.location.KlobucharIonosphericModel);
     method @NonNull public android.location.GpsAssistance.Builder setLeapSecondsModel(@Nullable android.location.LeapSecondsModel);
-    method @NonNull public android.location.GpsAssistance.Builder setRealTimeIntegrityModels(@Nullable java.util.List<android.location.RealTimeIntegrityModel>);
-    method @NonNull public android.location.GpsAssistance.Builder setSatelliteCorrections(@Nullable java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
-    method @NonNull public android.location.GpsAssistance.Builder setSatelliteEphemeris(@Nullable java.util.List<android.location.GpsSatelliteEphemeris>);
-    method @NonNull public android.location.GpsAssistance.Builder setTimeModels(@Nullable java.util.List<android.location.TimeModel>);
+    method @NonNull public android.location.GpsAssistance.Builder setRealTimeIntegrityModels(@NonNull java.util.List<android.location.RealTimeIntegrityModel>);
+    method @NonNull public android.location.GpsAssistance.Builder setSatelliteCorrections(@NonNull java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
+    method @NonNull public android.location.GpsAssistance.Builder setSatelliteEphemeris(@NonNull java.util.List<android.location.GpsSatelliteEphemeris>);
+    method @NonNull public android.location.GpsAssistance.Builder setTimeModels(@NonNull java.util.List<android.location.TimeModel>);
     method @NonNull public android.location.GpsAssistance.Builder setUtcModel(@Nullable android.location.UtcModel);
   }
 
@@ -916,11 +971,11 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class GpsSatelliteEphemeris implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsL2Params getGpsL2Params();
-    method @IntRange(from=1, to=32) public int getPrn();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsSatelliteClockModel getSatelliteClockModel();
     method @NonNull public android.location.SatelliteEphemerisTime getSatelliteEphemerisTime();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsSatelliteHealth getSatelliteHealth();
     method @NonNull public android.location.KeplerianOrbitModel getSatelliteOrbitModel();
+    method @IntRange(from=1, to=32) public int getSvid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GpsSatelliteEphemeris> CREATOR;
   }
@@ -929,11 +984,11 @@
     ctor public GpsSatelliteEphemeris.Builder();
     method @NonNull public android.location.GpsSatelliteEphemeris build();
     method @NonNull public android.location.GpsSatelliteEphemeris.Builder setGpsL2Params(@NonNull android.location.GpsSatelliteEphemeris.GpsL2Params);
-    method @NonNull public android.location.GpsSatelliteEphemeris.Builder setPrn(@IntRange(from=1, to=32) int);
     method @NonNull public android.location.GpsSatelliteEphemeris.Builder setSatelliteClockModel(@NonNull android.location.GpsSatelliteEphemeris.GpsSatelliteClockModel);
     method @NonNull public android.location.GpsSatelliteEphemeris.Builder setSatelliteEphemerisTime(@NonNull android.location.SatelliteEphemerisTime);
     method @NonNull public android.location.GpsSatelliteEphemeris.Builder setSatelliteHealth(@NonNull android.location.GpsSatelliteEphemeris.GpsSatelliteHealth);
     method @NonNull public android.location.GpsSatelliteEphemeris.Builder setSatelliteOrbitModel(@NonNull android.location.KeplerianOrbitModel);
+    method @NonNull public android.location.GpsSatelliteEphemeris.Builder setSvid(@IntRange(from=1, to=32) int);
   }
 
   public static final class GpsSatelliteEphemeris.GpsL2Params implements android.os.Parcelable {
@@ -1198,6 +1253,7 @@
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class QzssAssistance implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public android.location.GnssAlmanac getAlmanac();
+    method @Nullable public android.location.AuxiliaryInformation getAuxiliaryInformation();
     method @Nullable public android.location.KlobucharIonosphericModel getIonosphericModel();
     method @Nullable public android.location.LeapSecondsModel getLeapSecondsModel();
     method @NonNull public java.util.List<android.location.RealTimeIntegrityModel> getRealTimeIntegrityModels();
@@ -1213,23 +1269,24 @@
     ctor public QzssAssistance.Builder();
     method @NonNull public android.location.QzssAssistance build();
     method @NonNull public android.location.QzssAssistance.Builder setAlmanac(@Nullable android.location.GnssAlmanac);
+    method @NonNull public android.location.QzssAssistance.Builder setAuxiliaryInformation(@Nullable android.location.AuxiliaryInformation);
     method @NonNull public android.location.QzssAssistance.Builder setIonosphericModel(@Nullable android.location.KlobucharIonosphericModel);
     method @NonNull public android.location.QzssAssistance.Builder setLeapSecondsModel(@Nullable android.location.LeapSecondsModel);
-    method @NonNull public android.location.QzssAssistance.Builder setRealTimeIntegrityModels(@Nullable java.util.List<android.location.RealTimeIntegrityModel>);
-    method @NonNull public android.location.QzssAssistance.Builder setSatelliteCorrections(@Nullable java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
-    method @NonNull public android.location.QzssAssistance.Builder setSatelliteEphemeris(@Nullable java.util.List<android.location.QzssSatelliteEphemeris>);
-    method @NonNull public android.location.QzssAssistance.Builder setTimeModels(@Nullable java.util.List<android.location.TimeModel>);
+    method @NonNull public android.location.QzssAssistance.Builder setRealTimeIntegrityModels(@NonNull java.util.List<android.location.RealTimeIntegrityModel>);
+    method @NonNull public android.location.QzssAssistance.Builder setSatelliteCorrections(@NonNull java.util.List<android.location.GnssAssistance.GnssSatelliteCorrections>);
+    method @NonNull public android.location.QzssAssistance.Builder setSatelliteEphemeris(@NonNull java.util.List<android.location.QzssSatelliteEphemeris>);
+    method @NonNull public android.location.QzssAssistance.Builder setTimeModels(@NonNull java.util.List<android.location.TimeModel>);
     method @NonNull public android.location.QzssAssistance.Builder setUtcModel(@Nullable android.location.UtcModel);
   }
 
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class QzssSatelliteEphemeris implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsL2Params getGpsL2Params();
-    method @IntRange(from=183, to=206) public int getPrn();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsSatelliteClockModel getSatelliteClockModel();
     method @NonNull public android.location.SatelliteEphemerisTime getSatelliteEphemerisTime();
     method @NonNull public android.location.GpsSatelliteEphemeris.GpsSatelliteHealth getSatelliteHealth();
     method @NonNull public android.location.KeplerianOrbitModel getSatelliteOrbitModel();
+    method @IntRange(from=183, to=206) public int getSvid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.QzssSatelliteEphemeris> CREATOR;
   }
@@ -1238,22 +1295,22 @@
     ctor public QzssSatelliteEphemeris.Builder();
     method @NonNull public android.location.QzssSatelliteEphemeris build();
     method @NonNull public android.location.QzssSatelliteEphemeris.Builder setGpsL2Params(@NonNull android.location.GpsSatelliteEphemeris.GpsL2Params);
-    method @NonNull public android.location.QzssSatelliteEphemeris.Builder setPrn(@IntRange(from=183, to=206) int);
     method @NonNull public android.location.QzssSatelliteEphemeris.Builder setSatelliteClockModel(@NonNull android.location.GpsSatelliteEphemeris.GpsSatelliteClockModel);
     method @NonNull public android.location.QzssSatelliteEphemeris.Builder setSatelliteEphemerisTime(@NonNull android.location.SatelliteEphemerisTime);
     method @NonNull public android.location.QzssSatelliteEphemeris.Builder setSatelliteHealth(@NonNull android.location.GpsSatelliteEphemeris.GpsSatelliteHealth);
     method @NonNull public android.location.QzssSatelliteEphemeris.Builder setSatelliteOrbitModel(@NonNull android.location.KeplerianOrbitModel);
+    method @NonNull public android.location.QzssSatelliteEphemeris.Builder setSvid(@IntRange(from=183, to=206) int);
   }
 
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class RealTimeIntegrityModel implements android.os.Parcelable {
     method public int describeContents();
     method @NonNull public String getAdvisoryNumber();
     method @NonNull public String getAdvisoryType();
+    method @NonNull public java.util.List<android.location.GnssSignalType> getBadSignalTypes();
+    method @IntRange(from=1, to=206) public int getBadSvid();
     method @IntRange(from=0) public long getEndDateSeconds();
     method @IntRange(from=0) public long getPublishDateSeconds();
     method @IntRange(from=0) public long getStartDateSeconds();
-    method @IntRange(from=1, to=206) public int getSvid();
-    method public boolean isUsable();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.RealTimeIntegrityModel> CREATOR;
   }
@@ -1263,11 +1320,11 @@
     method @NonNull public android.location.RealTimeIntegrityModel build();
     method @NonNull public android.location.RealTimeIntegrityModel.Builder setAdvisoryNumber(@NonNull String);
     method @NonNull public android.location.RealTimeIntegrityModel.Builder setAdvisoryType(@NonNull String);
+    method @NonNull public android.location.RealTimeIntegrityModel.Builder setBadSignalTypes(@NonNull java.util.List<android.location.GnssSignalType>);
+    method @NonNull public android.location.RealTimeIntegrityModel.Builder setBadSvid(@IntRange(from=1, to=206) int);
     method @NonNull public android.location.RealTimeIntegrityModel.Builder setEndDateSeconds(@IntRange(from=0) long);
     method @NonNull public android.location.RealTimeIntegrityModel.Builder setPublishDateSeconds(@IntRange(from=0) long);
     method @NonNull public android.location.RealTimeIntegrityModel.Builder setStartDateSeconds(@IntRange(from=0) long);
-    method @NonNull public android.location.RealTimeIntegrityModel.Builder setSvid(@IntRange(from=1, to=206) int);
-    method @NonNull public android.location.RealTimeIntegrityModel.Builder setUsable(boolean);
   }
 
   @FlaggedApi("android.location.flags.gnss_assistance_interface") public final class SatelliteEphemerisTime implements android.os.Parcelable {
@@ -1435,6 +1492,13 @@
     field public static final String ACTION_GEOCODE_PROVIDER = "com.android.location.service.GeocodeProvider";
   }
 
+  @FlaggedApi("android.location.flags.gnss_assistance_interface") public abstract class GnssAssistanceProviderBase {
+    ctor public GnssAssistanceProviderBase(@NonNull android.content.Context, @NonNull String);
+    method @NonNull public final android.os.IBinder getBinder();
+    method public abstract void onRequest(@NonNull android.os.OutcomeReceiver<android.location.GnssAssistance,java.lang.Throwable>);
+    field public static final String ACTION_GNSS_ASSISTANCE_PROVIDER = "android.location.provider.action.GNSS_ASSISTANCE_PROVIDER";
+  }
+
   public abstract class LocationProviderBase {
     ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
     method @Nullable public final android.os.IBinder getBinder();
diff --git a/location/java/android/location/AuxiliaryInformation.java b/location/java/android/location/AuxiliaryInformation.java
new file mode 100644
index 0000000..601c87e
--- /dev/null
+++ b/location/java/android/location/AuxiliaryInformation.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.location.flags.Flags;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A class contains parameters to provide additional assistance information dependent on the GNSS
+ * constellation.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
+@SystemApi
+public final class AuxiliaryInformation implements Parcelable {
+
+    /**
+     * BDS B1C Satellite orbit type.
+     *
+     * <p>This is defined in BDS-SIS-ICD-B1I-3.0, section 3.1.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+        BDS_B1C_ORBIT_TYPE_UNDEFINED,
+        BDS_B1C_ORBIT_TYPE_GEO,
+        BDS_B1C_ORBIT_TYPE_IGSO,
+        BDS_B1C_ORBIT_TYPE_MEO
+    })
+    public @interface BeidouB1CSatelliteOrbitType {}
+
+    /**
+     * The following enumerations must be in sync with the values declared in
+     * AuxiliaryInformation.aidl.
+     */
+
+    /** The orbit type is undefined. */
+    public static final int BDS_B1C_ORBIT_TYPE_UNDEFINED = 0;
+
+    /** The orbit type is GEO. */
+    public static final int BDS_B1C_ORBIT_TYPE_GEO = 1;
+
+    /** The orbit type is IGSO. */
+    public static final int BDS_B1C_ORBIT_TYPE_IGSO = 2;
+
+    /** The orbit type is MEO. */
+    public static final int BDS_B1C_ORBIT_TYPE_MEO = 3;
+
+    /**
+     * Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle (SV), or OSN
+     * number for Glonass.
+     *
+     * <p>The distinction is made by looking at the constellation field. Values must be in the range
+     * of:
+     *
+     * <p>- GPS: 1-32
+     *
+     * <p>- GLONASS: 1-25
+     *
+     * <p>- QZSS: 183-206
+     *
+     * <p>- Galileo: 1-36
+     *
+     * <p>- Beidou: 1-63
+     */
+    private final int mSvid;
+
+    /** The list of available signal types for the satellite. */
+    @NonNull private final List<GnssSignalType> mAvailableSignalTypes;
+
+    /**
+     * Glonass carrier frequency number of the satellite. This is required for Glonass.
+     *
+     * <p>This is defined in Glonass ICD v5.1 section 3.3.1.1.
+     */
+    private final int mFrequencyChannelNumber;
+
+    /** BDS B1C satellite orbit type. This is required for Beidou. */
+    private final @BeidouB1CSatelliteOrbitType int mSatType;
+
+    private AuxiliaryInformation(Builder builder) {
+        // Allow Svid beyond the range to support potential future extensibility.
+        Preconditions.checkArgument(builder.mSvid >= 1);
+        Preconditions.checkNotNull(
+                builder.mAvailableSignalTypes, "AvailableSignalTypes cannot be null");
+        Preconditions.checkArgument(builder.mAvailableSignalTypes.size() > 0);
+        Preconditions.checkArgumentInRange(
+                builder.mFrequencyChannelNumber, -7, 6, "FrequencyChannelNumber");
+        Preconditions.checkArgumentInRange(
+                builder.mSatType, BDS_B1C_ORBIT_TYPE_UNDEFINED, BDS_B1C_ORBIT_TYPE_MEO, "SatType");
+        mSvid = builder.mSvid;
+        mAvailableSignalTypes =
+                Collections.unmodifiableList(new ArrayList<>(builder.mAvailableSignalTypes));
+        mFrequencyChannelNumber = builder.mFrequencyChannelNumber;
+        mSatType = builder.mSatType;
+    }
+
+    /**
+     * Returns the Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle
+     * (SV), or OSN number for Glonass.
+     *
+     * <p>The distinction is made by looking at the constellation field. Values must be in the range
+     * of:
+     *
+     * <p>- GPS: 1-32
+     *
+     * <p>- GLONASS: 1-25
+     *
+     * <p>- QZSS: 183-206
+     *
+     * <p>- Galileo: 1-36
+     *
+     * <p>- Beidou: 1-63
+     */
+    @IntRange(from = 1)
+    public int getSvid() {
+        return mSvid;
+    }
+
+    /** Returns the list of available signal types for the satellite. */
+    @NonNull
+    public List<GnssSignalType> getAvailableSignalTypes() {
+        return mAvailableSignalTypes;
+    }
+
+    /** Returns the Glonass carrier frequency number of the satellite. */
+    @IntRange(from = -7, to = 6)
+    public int getFrequencyChannelNumber() {
+        return mFrequencyChannelNumber;
+    }
+
+    /** Returns the BDS B1C satellite orbit type. */
+    @BeidouB1CSatelliteOrbitType
+    public int getSatType() {
+        return mSatType;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mSvid);
+        dest.writeTypedList(mAvailableSignalTypes);
+        dest.writeInt(mFrequencyChannelNumber);
+        dest.writeInt(mSatType);
+    }
+
+    @Override
+    @NonNull
+    public String toString() {
+        StringBuilder builder = new StringBuilder("AuxiliaryInformation[");
+        builder.append("svid = ").append(mSvid);
+        builder.append(", availableSignalTypes = ").append(mAvailableSignalTypes);
+        builder.append(", frequencyChannelNumber = ").append(mFrequencyChannelNumber);
+        builder.append(", satType = ").append(mSatType);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    public static final @NonNull Parcelable.Creator<AuxiliaryInformation> CREATOR =
+            new Parcelable.Creator<AuxiliaryInformation>() {
+                @Override
+                public AuxiliaryInformation createFromParcel(@NonNull Parcel in) {
+                    return new AuxiliaryInformation.Builder()
+                            .setSvid(in.readInt())
+                            .setAvailableSignalTypes(
+                                    in.createTypedArrayList(GnssSignalType.CREATOR))
+                            .setFrequencyChannelNumber(in.readInt())
+                            .setSatType(in.readInt())
+                            .build();
+                }
+
+                @Override
+                public AuxiliaryInformation[] newArray(int size) {
+                    return new AuxiliaryInformation[size];
+                }
+            };
+
+    /** A builder class for {@link AuxiliaryInformation}. */
+    public static final class Builder {
+        private int mSvid;
+        private List<GnssSignalType> mAvailableSignalTypes;
+        private int mFrequencyChannelNumber;
+        private @BeidouB1CSatelliteOrbitType int mSatType;
+
+        /**
+         * Sets the Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle
+         * (SV), or OSN number for Glonass.
+         *
+         * <p>The distinction is made by looking at the constellation field. Values must be in the
+         * range of:
+         *
+         * <p>- GPS: 1-32
+         *
+         * <p>- GLONASS: 1-25
+         *
+         * <p>- QZSS: 183-206
+         *
+         * <p>- Galileo: 1-36
+         *
+         * <p>- Beidou: 1-63
+         */
+        @NonNull
+        public Builder setSvid(@IntRange(from = 1) int svid) {
+            mSvid = svid;
+            return this;
+        }
+
+        /**
+         * Sets the list of available signal types for the satellite.
+         *
+         * <p>The list must be set and cannot be an empty list.
+         */
+        @NonNull
+        public Builder setAvailableSignalTypes(@NonNull List<GnssSignalType> availableSignalTypes) {
+            mAvailableSignalTypes = availableSignalTypes;
+            return this;
+        }
+
+        /** Sets the Glonass carrier frequency number of the satellite. */
+        @NonNull
+        public Builder setFrequencyChannelNumber(
+                @IntRange(from = -7, to = 6) int frequencyChannelNumber) {
+            mFrequencyChannelNumber = frequencyChannelNumber;
+            return this;
+        }
+
+        /** Sets the BDS B1C satellite orbit type. */
+        @NonNull
+        public Builder setSatType(@BeidouB1CSatelliteOrbitType int satType) {
+            mSatType = satType;
+            return this;
+        }
+
+        /** Builds a {@link AuxiliaryInformation} instance as specified by this builder. */
+        @NonNull
+        public AuxiliaryInformation build() {
+            return new AuxiliaryInformation(this);
+        }
+    }
+}
diff --git a/location/java/android/location/BeidouAssistance.java b/location/java/android/location/BeidouAssistance.java
index f55249e6..e35493e 100644
--- a/location/java/android/location/BeidouAssistance.java
+++ b/location/java/android/location/BeidouAssistance.java
@@ -19,7 +19,6 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.location.GnssAssistance.GnssSatelliteCorrections;
 import android.location.flags.Flags;
@@ -51,6 +50,9 @@
     /** The leap seconds model. */
     @Nullable private final LeapSecondsModel mLeapSecondsModel;
 
+    /** The auxiliary information. */
+    @Nullable private final AuxiliaryInformation mAuxiliaryInformation;
+
     /** The list of time models. */
     @NonNull private final List<TimeModel> mTimeModels;
 
@@ -68,6 +70,7 @@
         mIonosphericModel = builder.mIonosphericModel;
         mUtcModel = builder.mUtcModel;
         mLeapSecondsModel = builder.mLeapSecondsModel;
+        mAuxiliaryInformation = builder.mAuxiliaryInformation;
         if (builder.mTimeModels != null) {
             mTimeModels = Collections.unmodifiableList(new ArrayList<>(builder.mTimeModels));
         } else {
@@ -117,6 +120,12 @@
         return mLeapSecondsModel;
     }
 
+    /** Returns the auxiliary information. */
+    @Nullable
+    public AuxiliaryInformation getAuxiliaryInformation() {
+        return mAuxiliaryInformation;
+    }
+
     /** Returns the list of time models. */
     @NonNull
     public List<TimeModel> getTimeModels() {
@@ -154,6 +163,7 @@
         builder.append(", ionosphericModel = ").append(mIonosphericModel);
         builder.append(", utcModel = ").append(mUtcModel);
         builder.append(", leapSecondsModel = ").append(mLeapSecondsModel);
+        builder.append(", auxiliaryInformation = ").append(mAuxiliaryInformation);
         builder.append(", timeModels = ").append(mTimeModels);
         builder.append(", satelliteEphemeris = ").append(mSatelliteEphemeris);
         builder.append(", realTimeIntegrityModels = ").append(mRealTimeIntegrityModels);
@@ -168,6 +178,7 @@
         dest.writeTypedObject(mIonosphericModel, flags);
         dest.writeTypedObject(mUtcModel, flags);
         dest.writeTypedObject(mLeapSecondsModel, flags);
+        dest.writeTypedObject(mAuxiliaryInformation, flags);
         dest.writeTypedList(mTimeModels);
         dest.writeTypedList(mSatelliteEphemeris);
         dest.writeTypedList(mRealTimeIntegrityModels);
@@ -184,6 +195,8 @@
                                     in.readTypedObject(KlobucharIonosphericModel.CREATOR))
                             .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
                             .setLeapSecondsModel(in.readTypedObject(LeapSecondsModel.CREATOR))
+                            .setAuxiliaryInformation(
+                                    in.readTypedObject(AuxiliaryInformation.CREATOR))
                             .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
                             .setSatelliteEphemeris(
                                     in.createTypedArrayList(BeidouSatelliteEphemeris.CREATOR))
@@ -206,6 +219,7 @@
         private KlobucharIonosphericModel mIonosphericModel;
         private UtcModel mUtcModel;
         private LeapSecondsModel mLeapSecondsModel;
+        private AuxiliaryInformation mAuxiliaryInformation;
         private List<TimeModel> mTimeModels;
         private List<BeidouSatelliteEphemeris> mSatelliteEphemeris;
         private List<RealTimeIntegrityModel> mRealTimeIntegrityModels;
@@ -239,10 +253,17 @@
             return this;
         }
 
+        /** Sets the auxiliary information. */
+        @NonNull
+        public Builder setAuxiliaryInformation(
+                @Nullable AuxiliaryInformation auxiliaryInformation) {
+            mAuxiliaryInformation = auxiliaryInformation;
+            return this;
+        }
+
         /** Sets the list of time models. */
         @NonNull
-        public Builder setTimeModels(
-                @Nullable @SuppressLint("NullableCollection") List<TimeModel> timeModels) {
+        public Builder setTimeModels(@NonNull List<TimeModel> timeModels) {
             mTimeModels = timeModels;
             return this;
         }
@@ -250,8 +271,7 @@
         /** Sets the list of Beidou ephemeris. */
         @NonNull
         public Builder setSatelliteEphemeris(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<BeidouSatelliteEphemeris> satelliteEphemeris) {
+                @NonNull List<BeidouSatelliteEphemeris> satelliteEphemeris) {
             mSatelliteEphemeris = satelliteEphemeris;
             return this;
         }
@@ -259,8 +279,7 @@
         /** Sets the list of real time integrity models. */
         @NonNull
         public Builder setRealTimeIntegrityModels(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<RealTimeIntegrityModel> realTimeIntegrityModels) {
+                @NonNull List<RealTimeIntegrityModel> realTimeIntegrityModels) {
             mRealTimeIntegrityModels = realTimeIntegrityModels;
             return this;
         }
@@ -268,8 +287,7 @@
         /** Sets the list of Beidou satellite corrections. */
         @NonNull
         public Builder setSatelliteCorrections(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GnssSatelliteCorrections> satelliteCorrections) {
+                @NonNull List<GnssSatelliteCorrections> satelliteCorrections) {
             mSatelliteCorrections = satelliteCorrections;
             return this;
         }
diff --git a/location/java/android/location/BeidouSatelliteEphemeris.java b/location/java/android/location/BeidouSatelliteEphemeris.java
index 6bd91e3..3382c20 100644
--- a/location/java/android/location/BeidouSatelliteEphemeris.java
+++ b/location/java/android/location/BeidouSatelliteEphemeris.java
@@ -35,8 +35,8 @@
 @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
 @SystemApi
 public final class BeidouSatelliteEphemeris implements Parcelable {
-    /** The PRN number of the Beidou satellite. */
-    private final int mPrn;
+    /** The PRN or satellite ID number for the Beidou satellite. */
+    private final int mSvid;
 
     /** Satellite clock model. */
     private final BeidouSatelliteClockModel mSatelliteClockModel;
@@ -51,8 +51,8 @@
     private final BeidouSatelliteEphemerisTime mSatelliteEphemerisTime;
 
     private BeidouSatelliteEphemeris(Builder builder) {
-        // Allow PRN beyond the range to support potential future extensibility.
-        Preconditions.checkArgument(builder.mPrn >= 1);
+        // Allow Svid beyond the range to support potential future extensibility.
+        Preconditions.checkArgument(builder.mSvid >= 1);
         Preconditions.checkNotNull(builder.mSatelliteClockModel,
                 "SatelliteClockModel cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteOrbitModel,
@@ -61,17 +61,17 @@
                 "SatelliteHealth cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteEphemerisTime,
                 "SatelliteEphemerisTime cannot be null");
-        mPrn = builder.mPrn;
+        mSvid = builder.mSvid;
         mSatelliteClockModel = builder.mSatelliteClockModel;
         mSatelliteOrbitModel = builder.mSatelliteOrbitModel;
         mSatelliteHealth = builder.mSatelliteHealth;
         mSatelliteEphemerisTime = builder.mSatelliteEphemerisTime;
     }
 
-    /** Returns the PRN of the satellite. */
+    /** Returns the PRN or satellite ID number for the Beidou satellite. */
     @IntRange(from = 1, to = 63)
-    public int getPrn() {
-        return mPrn;
+    public int getSvid() {
+        return mSvid;
     }
 
     /** Returns the satellite clock model. */
@@ -105,7 +105,7 @@
                 public BeidouSatelliteEphemeris createFromParcel(Parcel in) {
                     final BeidouSatelliteEphemeris.Builder beidouSatelliteEphemeris =
                             new Builder()
-                                    .setPrn(in.readInt())
+                                    .setSvid(in.readInt())
                                     .setSatelliteClockModel(
                                             in.readTypedObject(BeidouSatelliteClockModel.CREATOR))
                                     .setSatelliteOrbitModel(
@@ -131,7 +131,7 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
-        parcel.writeInt(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeTypedObject(mSatelliteClockModel, flags);
         parcel.writeTypedObject(mSatelliteOrbitModel, flags);
         parcel.writeTypedObject(mSatelliteHealth, flags);
@@ -142,7 +142,7 @@
     @NonNull
     public String toString() {
         StringBuilder builder = new StringBuilder("BeidouSatelliteEphemeris[");
-        builder.append("prn = ").append(mPrn);
+        builder.append("svid = ").append(mSvid);
         builder.append(", satelliteClockModel = ").append(mSatelliteClockModel);
         builder.append(", satelliteOrbitModel = ").append(mSatelliteOrbitModel);
         builder.append(", satelliteHealth = ").append(mSatelliteHealth);
@@ -153,16 +153,16 @@
 
     /** Builder for {@link BeidouSatelliteEphemeris} */
     public static final class Builder {
-        private int mPrn;
+        private int mSvid;
         private BeidouSatelliteClockModel mSatelliteClockModel;
         private KeplerianOrbitModel mSatelliteOrbitModel;
         private BeidouSatelliteHealth mSatelliteHealth;
         private BeidouSatelliteEphemerisTime mSatelliteEphemerisTime;
 
-        /** Sets the PRN of the satellite. */
+        /** Sets the PRN or satellite ID number for the Beidou satellite. */
         @NonNull
-        public Builder setPrn(int prn) {
-            mPrn = prn;
+        public Builder setSvid(int svid) {
+            mSvid = svid;
             return this;
         }
 
diff --git a/location/java/android/location/GalileoAssistance.java b/location/java/android/location/GalileoAssistance.java
index 07c5bab..8a09e66 100644
--- a/location/java/android/location/GalileoAssistance.java
+++ b/location/java/android/location/GalileoAssistance.java
@@ -19,7 +19,6 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.location.GnssAssistance.GnssSatelliteCorrections;
 import android.location.flags.Flags;
@@ -51,6 +50,9 @@
     /** The leap seconds model. */
     @Nullable private final LeapSecondsModel mLeapSecondsModel;
 
+    /** The auxiliary information. */
+    @Nullable private final AuxiliaryInformation mAuxiliaryInformation;
+
     /** The list of time models. */
     @NonNull private final List<TimeModel> mTimeModels;
 
@@ -68,6 +70,7 @@
         mIonosphericModel = builder.mIonosphericModel;
         mUtcModel = builder.mUtcModel;
         mLeapSecondsModel = builder.mLeapSecondsModel;
+        mAuxiliaryInformation = builder.mAuxiliaryInformation;
         if (builder.mTimeModels != null) {
             mTimeModels = Collections.unmodifiableList(new ArrayList<>(builder.mTimeModels));
         } else {
@@ -117,6 +120,12 @@
         return mLeapSecondsModel;
     }
 
+    /** Returns the auxiliary information. */
+    @Nullable
+    public AuxiliaryInformation getAuxiliaryInformation() {
+        return mAuxiliaryInformation;
+    }
+
     /** Returns the list of time models. */
     @NonNull
     public List<TimeModel> getTimeModels() {
@@ -152,6 +161,7 @@
         dest.writeTypedObject(mIonosphericModel, flags);
         dest.writeTypedObject(mUtcModel, flags);
         dest.writeTypedObject(mLeapSecondsModel, flags);
+        dest.writeTypedObject(mAuxiliaryInformation, flags);
         dest.writeTypedList(mTimeModels);
         dest.writeTypedList(mSatelliteEphemeris);
         dest.writeTypedList(mRealTimeIntegrityModels);
@@ -166,6 +176,7 @@
         builder.append(", ionosphericModel = ").append(mIonosphericModel);
         builder.append(", utcModel = ").append(mUtcModel);
         builder.append(", leapSecondsModel = ").append(mLeapSecondsModel);
+        builder.append(", auxiliaryInformation = ").append(mAuxiliaryInformation);
         builder.append(", timeModels = ").append(mTimeModels);
         builder.append(", satelliteEphemeris = ").append(mSatelliteEphemeris);
         builder.append(", realTimeIntegrityModels = ").append(mRealTimeIntegrityModels);
@@ -184,6 +195,8 @@
                                     in.readTypedObject(KlobucharIonosphericModel.CREATOR))
                             .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
                             .setLeapSecondsModel(in.readTypedObject(LeapSecondsModel.CREATOR))
+                            .setAuxiliaryInformation(
+                                    in.readTypedObject(AuxiliaryInformation.CREATOR))
                             .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
                             .setSatelliteEphemeris(
                                     in.createTypedArrayList(GalileoSatelliteEphemeris.CREATOR))
@@ -206,6 +219,7 @@
         private KlobucharIonosphericModel mIonosphericModel;
         private UtcModel mUtcModel;
         private LeapSecondsModel mLeapSecondsModel;
+        private AuxiliaryInformation mAuxiliaryInformation;
         private List<TimeModel> mTimeModels;
         private List<GalileoSatelliteEphemeris> mSatelliteEphemeris;
         private List<RealTimeIntegrityModel> mRealTimeIntegrityModels;
@@ -239,10 +253,17 @@
             return this;
         }
 
+        /** Sets the auxiliary information. */
+        @NonNull
+        public Builder setAuxiliaryInformation(
+                @Nullable AuxiliaryInformation auxiliaryInformation) {
+            mAuxiliaryInformation = auxiliaryInformation;
+            return this;
+        }
+
         /** Sets the list of time models. */
         @NonNull
-        public Builder setTimeModels(
-                @Nullable @SuppressLint("NullableCollection") List<TimeModel> timeModels) {
+        public Builder setTimeModels(@NonNull List<TimeModel> timeModels) {
             mTimeModels = timeModels;
             return this;
         }
@@ -250,8 +271,7 @@
         /** Sets the list of Galileo ephemeris. */
         @NonNull
         public Builder setSatelliteEphemeris(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GalileoSatelliteEphemeris> satelliteEphemeris) {
+                @NonNull List<GalileoSatelliteEphemeris> satelliteEphemeris) {
             mSatelliteEphemeris = satelliteEphemeris;
             return this;
         }
@@ -259,8 +279,7 @@
         /** Sets the list of real time integrity models. */
         @NonNull
         public Builder setRealTimeIntegrityModels(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<RealTimeIntegrityModel> realTimeIntegrityModels) {
+                @NonNull List<RealTimeIntegrityModel> realTimeIntegrityModels) {
             mRealTimeIntegrityModels = realTimeIntegrityModels;
             return this;
         }
@@ -268,8 +287,7 @@
         /** Sets the list of Galileo satellite corrections. */
         @NonNull
         public Builder setSatelliteCorrections(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GnssSatelliteCorrections> satelliteCorrections) {
+                @NonNull List<GnssSatelliteCorrections> satelliteCorrections) {
             mSatelliteCorrections = satelliteCorrections;
             return this;
         }
diff --git a/location/java/android/location/GalileoSatelliteEphemeris.java b/location/java/android/location/GalileoSatelliteEphemeris.java
index 7dd3711..08218f4 100644
--- a/location/java/android/location/GalileoSatelliteEphemeris.java
+++ b/location/java/android/location/GalileoSatelliteEphemeris.java
@@ -43,8 +43,8 @@
 @SystemApi
 public final class GalileoSatelliteEphemeris implements Parcelable {
 
-    /** Satellite code number. */
-    private int mSatelliteCodeNumber;
+    /** PRN or satellite ID number for the Galileo satellite. */
+    private int mSvid;
 
     /** Array of satellite clock model. */
     @NonNull private final List<GalileoSatelliteClockModel> mSatelliteClockModels;
@@ -59,8 +59,8 @@
     @NonNull private final SatelliteEphemerisTime mSatelliteEphemerisTime;
 
     private GalileoSatelliteEphemeris(Builder builder) {
-        // Allow satelliteCodeNumber beyond the range to support potential future extensibility.
-        Preconditions.checkArgument(builder.mSatelliteCodeNumber >= 1);
+        // Allow svid beyond the range to support potential future extensibility.
+        Preconditions.checkArgument(builder.mSvid >= 1);
         Preconditions.checkNotNull(
                 builder.mSatelliteClockModels, "SatelliteClockModels cannot be null");
         Preconditions.checkNotNull(
@@ -68,7 +68,7 @@
         Preconditions.checkNotNull(builder.mSatelliteHealth, "SatelliteHealth cannot be null");
         Preconditions.checkNotNull(
                 builder.mSatelliteEphemerisTime, "SatelliteEphemerisTime cannot be null");
-        mSatelliteCodeNumber = builder.mSatelliteCodeNumber;
+        mSvid = builder.mSvid;
         final List<GalileoSatelliteClockModel> satelliteClockModels = builder.mSatelliteClockModels;
         mSatelliteClockModels = Collections.unmodifiableList(new ArrayList<>(satelliteClockModels));
         mSatelliteOrbitModel = builder.mSatelliteOrbitModel;
@@ -76,10 +76,10 @@
         mSatelliteEphemerisTime = builder.mSatelliteEphemerisTime;
     }
 
-    /** Returns the satellite code number. */
+    /** Returns the PRN or satellite ID number for the Galileo satellite. */
     @IntRange(from = 1, to = 36)
-    public int getSatelliteCodeNumber() {
-        return mSatelliteCodeNumber;
+    public int getSvid() {
+        return mSvid;
     }
 
     /** Returns the list of satellite clock models. */
@@ -113,7 +113,7 @@
                 public GalileoSatelliteEphemeris createFromParcel(Parcel in) {
                     final GalileoSatelliteEphemeris.Builder galileoSatelliteEphemeris =
                             new Builder();
-                    galileoSatelliteEphemeris.setSatelliteCodeNumber(in.readInt());
+                    galileoSatelliteEphemeris.setSvid(in.readInt());
                     List<GalileoSatelliteClockModel> satelliteClockModels = new ArrayList<>();
                     in.readTypedList(satelliteClockModels, GalileoSatelliteClockModel.CREATOR);
                     galileoSatelliteEphemeris.setSatelliteClockModels(satelliteClockModels);
@@ -139,7 +139,7 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
-        parcel.writeInt(mSatelliteCodeNumber);
+        parcel.writeInt(mSvid);
         parcel.writeTypedList(mSatelliteClockModels, flags);
         parcel.writeTypedObject(mSatelliteOrbitModel, flags);
         parcel.writeTypedObject(mSatelliteHealth, flags);
@@ -150,7 +150,7 @@
     @NonNull
     public String toString() {
         StringBuilder builder = new StringBuilder("GalileoSatelliteEphemeris[");
-        builder.append("satelliteCodeNumber = ").append(mSatelliteCodeNumber);
+        builder.append("svid = ").append(mSvid);
         builder.append(", satelliteClockModels = ").append(mSatelliteClockModels);
         builder.append(", satelliteOrbitModel = ").append(mSatelliteOrbitModel);
         builder.append(", satelliteHealth = ").append(mSatelliteHealth);
@@ -161,17 +161,16 @@
 
     /** Builder for {@link GalileoSatelliteEphemeris}. */
     public static final class Builder {
-        private int mSatelliteCodeNumber;
+        private int mSvid;
         private List<GalileoSatelliteClockModel> mSatelliteClockModels;
         private KeplerianOrbitModel mSatelliteOrbitModel;
         private GalileoSvHealth mSatelliteHealth;
         private SatelliteEphemerisTime mSatelliteEphemerisTime;
 
-        /** Sets the satellite code number. */
+        /** Sets the PRN or satellite ID number for the Galileo satellite. */
         @NonNull
-        public Builder setSatelliteCodeNumber(
-                @IntRange(from = 1, to = 36) int satelliteCodeNumber) {
-            mSatelliteCodeNumber = satelliteCodeNumber;
+        public Builder setSvid(@IntRange(from = 1, to = 36) int svid) {
+            mSvid = svid;
             return this;
         }
 
@@ -218,37 +217,107 @@
      * <p>This is defined in Galileo-OS-SIS-ICD 5.1.9.3.
      */
     public static final class GalileoSvHealth implements Parcelable {
+
+        /**
+         * Galileo data validity status.
+         *
+         * @hide
+         */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({DATA_STATUS_DATA_VALID, DATA_STATUS_WORKING_WITHOUT_GUARANTEE})
+        public @interface GalileoDataValidityStatus {}
+
+        /**
+         * The following enumerations must be in sync with the values declared in
+         * GalileoHealthDataVaidityType in GalileoSatelliteEphemeris.aidl.
+         */
+
+        /** Data validity status is data valid. */
+        public static final int DATA_STATUS_DATA_VALID = 0;
+
+        /** Data validity status is working without guarantee. */
+        public static final int DATA_STATUS_WORKING_WITHOUT_GUARANTEE = 1;
+
+        /**
+         * Galileo signal health status.
+         *
+         * @hide
+         */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({
+            HEALTH_STATUS_OK,
+            HEALTH_STATUS_OUT_OF_SERVICE,
+            HEALTH_STATUS_EXTENDED_OPERATION_MODE,
+            HEALTH_STATUS_IN_TEST
+        })
+        public @interface GalileoHealthStatus {}
+
+        /**
+         * The following enumerations must be in sync with the values declared in
+         * GalileoHealthStatusType in GalileoSatelliteEphemeris.aidl.
+         */
+
+        /** Health status is ok. */
+        public static final int HEALTH_STATUS_OK = 0;
+
+        /** Health status is out of service. */
+        public static final int HEALTH_STATUS_OUT_OF_SERVICE = 1;
+
+        /** Health status is in extended operation mode. */
+        public static final int HEALTH_STATUS_EXTENDED_OPERATION_MODE = 2;
+
+        /** Health status is in test mode. */
+        public static final int HEALTH_STATUS_IN_TEST = 3;
+
         /** E1-B data validity status. */
-        private int mDataValidityStatusE1b;
+        private @GalileoDataValidityStatus int mDataValidityStatusE1b;
 
         /** E1-B/C signal health status. */
-        private int mSignalHealthStatusE1b;
+        private @GalileoHealthStatus int mSignalHealthStatusE1b;
 
         /** E5a data validity status. */
-        private int mDataValidityStatusE5a;
+        private @GalileoDataValidityStatus int mDataValidityStatusE5a;
 
         /** E5a signal health status. */
-        private int mSignalHealthStatusE5a;
+        private @GalileoHealthStatus int mSignalHealthStatusE5a;
 
         /** E5b data validity status. */
-        private int mDataValidityStatusE5b;
+        private @GalileoDataValidityStatus int mDataValidityStatusE5b;
 
         /** E5b signal health status. */
-        private int mSignalHealthStatusE5b;
+        private @GalileoHealthStatus int mSignalHealthStatusE5b;
 
         private GalileoSvHealth(Builder builder) {
             Preconditions.checkArgumentInRange(
-                    builder.mDataValidityStatusE1b, 0, 1, "DataValidityStatusE1b");
+                    builder.mDataValidityStatusE1b,
+                    DATA_STATUS_DATA_VALID,
+                    DATA_STATUS_WORKING_WITHOUT_GUARANTEE,
+                    "DataValidityStatusE1b");
             Preconditions.checkArgumentInRange(
-                    builder.mSignalHealthStatusE1b, 0, 3, "SignalHealthStatusE1b");
+                    builder.mSignalHealthStatusE1b,
+                    HEALTH_STATUS_OK,
+                    HEALTH_STATUS_IN_TEST,
+                    "SignalHealthStatusE1b");
             Preconditions.checkArgumentInRange(
-                    builder.mDataValidityStatusE5a, 0, 1, "DataValidityStatusE5a");
+                    builder.mDataValidityStatusE5a,
+                    DATA_STATUS_DATA_VALID,
+                    DATA_STATUS_WORKING_WITHOUT_GUARANTEE,
+                    "DataValidityStatusE5a");
             Preconditions.checkArgumentInRange(
-                    builder.mSignalHealthStatusE5a, 0, 3, "SignalHealthStatusE5a");
+                    builder.mSignalHealthStatusE5a,
+                    HEALTH_STATUS_OK,
+                    HEALTH_STATUS_IN_TEST,
+                    "SignalHealthStatusE5a");
             Preconditions.checkArgumentInRange(
-                    builder.mDataValidityStatusE5b, 0, 1, "DataValidityStatusE5b");
+                    builder.mDataValidityStatusE5b,
+                    DATA_STATUS_DATA_VALID,
+                    DATA_STATUS_WORKING_WITHOUT_GUARANTEE,
+                    "DataValidityStatusE5b");
             Preconditions.checkArgumentInRange(
-                    builder.mSignalHealthStatusE5b, 0, 3, "SignalHealthStatusE5b");
+                    builder.mSignalHealthStatusE5b,
+                    HEALTH_STATUS_OK,
+                    HEALTH_STATUS_IN_TEST,
+                    "SignalHealthStatusE5b");
             mDataValidityStatusE1b = builder.mDataValidityStatusE1b;
             mSignalHealthStatusE1b = builder.mSignalHealthStatusE1b;
             mDataValidityStatusE5a = builder.mDataValidityStatusE5a;
@@ -258,37 +327,37 @@
         }
 
         /** Returns the E1-B data validity status. */
-        @IntRange(from = 0, to = 1)
+        @GalileoDataValidityStatus
         public int getDataValidityStatusE1b() {
             return mDataValidityStatusE1b;
         }
 
         /** Returns the E1-B/C signal health status. */
-        @IntRange(from = 0, to = 3)
+        @GalileoHealthStatus
         public int getSignalHealthStatusE1b() {
             return mSignalHealthStatusE1b;
         }
 
         /** Returns the E5a data validity status. */
-        @IntRange(from = 0, to = 1)
+        @GalileoDataValidityStatus
         public int getDataValidityStatusE5a() {
             return mDataValidityStatusE5a;
         }
 
         /** Returns the E5a signal health status. */
-        @IntRange(from = 0, to = 3)
+        @GalileoHealthStatus
         public int getSignalHealthStatusE5a() {
             return mSignalHealthStatusE5a;
         }
 
         /** Returns the E5b data validity status. */
-        @IntRange(from = 0, to = 1)
+        @GalileoDataValidityStatus
         public int getDataValidityStatusE5b() {
             return mDataValidityStatusE5b;
         }
 
         /** Returns the E5b signal health status. */
-        @IntRange(from = 0, to = 3)
+        @GalileoHealthStatus
         public int getSignalHealthStatusE5b() {
             return mSignalHealthStatusE5b;
         }
@@ -355,7 +424,7 @@
             /** Sets the E1-B data validity status. */
             @NonNull
             public Builder setDataValidityStatusE1b(
-                    @IntRange(from = 0, to = 1) int dataValidityStatusE1b) {
+                    @GalileoDataValidityStatus int dataValidityStatusE1b) {
                 mDataValidityStatusE1b = dataValidityStatusE1b;
                 return this;
             }
@@ -363,7 +432,7 @@
             /** Sets the E1-B/C signal health status. */
             @NonNull
             public Builder setSignalHealthStatusE1b(
-                    @IntRange(from = 0, to = 3) int signalHealthStatusE1b) {
+                    @GalileoHealthStatus int signalHealthStatusE1b) {
                 mSignalHealthStatusE1b = signalHealthStatusE1b;
                 return this;
             }
@@ -371,7 +440,7 @@
             /** Sets the E5a data validity status. */
             @NonNull
             public Builder setDataValidityStatusE5a(
-                    @IntRange(from = 0, to = 1) int dataValidityStatusE5a) {
+                    @GalileoDataValidityStatus int dataValidityStatusE5a) {
                 mDataValidityStatusE5a = dataValidityStatusE5a;
                 return this;
             }
@@ -379,7 +448,7 @@
             /** Sets the E5a signal health status. */
             @NonNull
             public Builder setSignalHealthStatusE5a(
-                    @IntRange(from = 0, to = 3) int signalHealthStatusE5a) {
+                    @GalileoHealthStatus int signalHealthStatusE5a) {
                 mSignalHealthStatusE5a = signalHealthStatusE5a;
                 return this;
             }
@@ -387,7 +456,7 @@
             /** Sets the E5b data validity status. */
             @NonNull
             public Builder setDataValidityStatusE5b(
-                    @IntRange(from = 0, to = 1) int dataValidityStatusE5b) {
+                    @GalileoDataValidityStatus int dataValidityStatusE5b) {
                 mDataValidityStatusE5b = dataValidityStatusE5b;
                 return this;
             }
@@ -395,7 +464,7 @@
             /** Sets the E5b signal health status. */
             @NonNull
             public Builder setSignalHealthStatusE5b(
-                    @IntRange(from = 0, to = 3) int signalHealthStatusE5b) {
+                    @GalileoHealthStatus int signalHealthStatusE5b) {
                 mSignalHealthStatusE5b = signalHealthStatusE5b;
                 return this;
             }
diff --git a/location/java/android/location/GlonassAlmanac.java b/location/java/android/location/GlonassAlmanac.java
index 861dc5d..3765743 100644
--- a/location/java/android/location/GlonassAlmanac.java
+++ b/location/java/android/location/GlonassAlmanac.java
@@ -21,6 +21,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.location.GlonassSatelliteEphemeris.GlonassHealthStatus;
 import android.location.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -121,11 +122,17 @@
         /** Slot number. */
         private final int mSlotNumber;
 
-        /** Satellite health information (0=healthy, 1=unhealthy). */
-        private final int mSvHealth;
+        /** Satellite health status. */
+        private final @GlonassHealthStatus int mHealthState;
 
         /** Frequency channel number. */
-        private final int mFreqChannel;
+        private final int mFrequencyChannelNumber;
+
+        /** Calendar day number within the four-year period beginning since the leap year. */
+        private final int mCalendarDayNumber;
+
+        /** Flag to indicates if the satellite is a GLONASS-M satellitee. */
+        private final boolean mGlonassM;
 
         /** Coarse value of satellite time correction to GLONASS time in seconds. */
         private final double mTau;
@@ -148,15 +155,18 @@
         /** Eccentricity. */
         private final double mEccentricity;
 
-        /** Argument of perigee in radians. */
+        /** Argument of perigee in semi-circles. */
         private final double mOmega;
 
         private GlonassSatelliteAlmanac(Builder builder) {
             // Allow slotNumber beyond the range to support potential future extensibility.
             Preconditions.checkArgument(builder.mSlotNumber >= 1);
-            // Allow svHealth beyond the range to support potential future extensibility.
-            Preconditions.checkArgument(builder.mSvHealth >= 0);
-            Preconditions.checkArgumentInRange(builder.mFreqChannel, 0, 31, "FreqChannel");
+            // Allow healthState beyond the range to support potential future extensibility.
+            Preconditions.checkArgument(builder.mHealthState >= 0);
+            Preconditions.checkArgumentInRange(
+                    builder.mFrequencyChannelNumber, 0, 31, "FrequencyChannelNumber");
+            Preconditions.checkArgumentInRange(
+                    builder.mCalendarDayNumber, 1, 1461, "CalendarDayNumber");
             Preconditions.checkArgumentInRange(builder.mTau, -1.9e-3f, 1.9e-3f, "Tau");
             Preconditions.checkArgumentInRange(builder.mTLambda, 0.0f, 44100.0f, "TLambda");
             Preconditions.checkArgumentInRange(builder.mLambda, -1.0f, 1.0f, "Lambda");
@@ -166,8 +176,10 @@
             Preconditions.checkArgumentInRange(builder.mEccentricity, 0.0f, 0.03f, "Eccentricity");
             Preconditions.checkArgumentInRange(builder.mOmega, -1.0f, 1.0f, "Omega");
             mSlotNumber = builder.mSlotNumber;
-            mSvHealth = builder.mSvHealth;
-            mFreqChannel = builder.mFreqChannel;
+            mHealthState = builder.mHealthState;
+            mFrequencyChannelNumber = builder.mFrequencyChannelNumber;
+            mCalendarDayNumber = builder.mCalendarDayNumber;
+            mGlonassM = builder.mGlonassM;
             mTau = builder.mTau;
             mTLambda = builder.mTLambda;
             mLambda = builder.mLambda;
@@ -184,16 +196,29 @@
             return mSlotNumber;
         }
 
-        /** Returns the Satellite health information (0=healthy, 1=unhealthy). */
-        @IntRange(from = 0, to = 1)
-        public int getSvHealth() {
-            return mSvHealth;
+        /** Returns the satellite health status. */
+        public @GlonassHealthStatus int getHealthState() {
+            return mHealthState;
         }
 
         /** Returns the frequency channel number. */
         @IntRange(from = 0, to = 31)
-        public int getFreqChannel() {
-            return mFreqChannel;
+        public int getFrequencyChannelNumber() {
+            return mFrequencyChannelNumber;
+        }
+
+        /**
+         * Returns the calendar day number within the four-year period beginning since the leap
+         * year.
+         */
+        @IntRange(from = 1, to = 1461)
+        public int getCalendarDayNumber() {
+            return mCalendarDayNumber;
+        }
+
+        /** Returns true if the satellite is a GLONASS-M satellitee, false otherwise. */
+        public boolean isGlonassM() {
+            return mGlonassM;
         }
 
         /** Returns the coarse value of satellite time correction to GLONASS time in seconds. */
@@ -241,7 +266,7 @@
             return mEccentricity;
         }
 
-        /** Returns the argument of perigee in radians. */
+        /** Returns the Argument of perigee in semi-circles. */
         @FloatRange(from = -1.0f, to = 1.0f)
         public double getOmega() {
             return mOmega;
@@ -255,8 +280,10 @@
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeInt(mSlotNumber);
-            dest.writeInt(mSvHealth);
-            dest.writeInt(mFreqChannel);
+            dest.writeInt(mHealthState);
+            dest.writeInt(mFrequencyChannelNumber);
+            dest.writeInt(mCalendarDayNumber);
+            dest.writeBoolean(mGlonassM);
             dest.writeDouble(mTau);
             dest.writeDouble(mTLambda);
             dest.writeDouble(mLambda);
@@ -273,8 +300,10 @@
                     public GlonassSatelliteAlmanac createFromParcel(@NonNull Parcel source) {
                         return new GlonassSatelliteAlmanac.Builder()
                                 .setSlotNumber(source.readInt())
-                                .setSvHealth(source.readInt())
-                                .setFreqChannel(source.readInt())
+                                .setHealthState(source.readInt())
+                                .setFrequencyChannelNumber(source.readInt())
+                                .setCalendarDayNumber(source.readInt())
+                                .setGlonassM(source.readBoolean())
                                 .setTau(source.readDouble())
                                 .setTLambda(source.readDouble())
                                 .setLambda(source.readDouble())
@@ -297,8 +326,10 @@
         public String toString() {
             StringBuilder builder = new StringBuilder("GlonassSatelliteAlmanac[");
             builder.append("slotNumber = ").append(mSlotNumber);
-            builder.append(", svHealth = ").append(mSvHealth);
-            builder.append(", freqChannel = ").append(mFreqChannel);
+            builder.append(", healthState = ").append(mHealthState);
+            builder.append(", frequencyChannelNumber = ").append(mFrequencyChannelNumber);
+            builder.append(", calendarDayNumber = ").append(mCalendarDayNumber);
+            builder.append(", glonassM = ").append(mGlonassM);
             builder.append(", tau = ").append(mTau);
             builder.append(", tLambda = ").append(mTLambda);
             builder.append(", lambda = ").append(mLambda);
@@ -314,8 +345,10 @@
         /** Builder for {@link GlonassSatelliteAlmanac}. */
         public static final class Builder {
             private int mSlotNumber;
-            private int mSvHealth;
-            private int mFreqChannel;
+            private int mHealthState;
+            private int mFrequencyChannelNumber;
+            private int mCalendarDayNumber;
+            private boolean mGlonassM;
             private double mTau;
             private double mTLambda;
             private double mLambda;
@@ -332,17 +365,36 @@
                 return this;
             }
 
-            /** Sets the Satellite health information (0=healthy, 1=unhealthy). */
+            /** Sets the satellite health status. */
             @NonNull
-            public Builder setSvHealth(@IntRange(from = 0, to = 1) int svHealth) {
-                mSvHealth = svHealth;
+            public Builder setHealthState(@GlonassHealthStatus int healthState) {
+                mHealthState = healthState;
                 return this;
             }
 
             /** Sets the frequency channel number. */
             @NonNull
-            public Builder setFreqChannel(@IntRange(from = 0, to = 31) int freqChannel) {
-                mFreqChannel = freqChannel;
+            public Builder setFrequencyChannelNumber(
+                    @IntRange(from = 0, to = 31) int frequencyChannelNumber) {
+                mFrequencyChannelNumber = frequencyChannelNumber;
+                return this;
+            }
+
+            /**
+             * Sets the calendar day number within the four-year period beginning since the leap
+             * year.
+             */
+            @NonNull
+            public Builder setCalendarDayNumber(
+                    @IntRange(from = 1, to = 1461) int calendarDayNumber) {
+                mCalendarDayNumber = calendarDayNumber;
+                return this;
+            }
+
+            /** Sets to true if the satellite is a GLONASS-M satellitee, false otherwise. */
+            @NonNull
+            public Builder setGlonassM(boolean isGlonassM) {
+                this.mGlonassM = isGlonassM;
                 return this;
             }
 
@@ -401,7 +453,7 @@
                 return this;
             }
 
-            /** Sets the argument of perigee in radians. */
+            /** Sets the Argument of perigee in semi-circles. */
             @NonNull
             public Builder setOmega(@FloatRange(from = -1.0f, to = 1.0f) double omega) {
                 mOmega = omega;
diff --git a/location/java/android/location/GlonassAssistance.java b/location/java/android/location/GlonassAssistance.java
index cc08201..c7ed1c5 100644
--- a/location/java/android/location/GlonassAssistance.java
+++ b/location/java/android/location/GlonassAssistance.java
@@ -19,7 +19,6 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.location.GnssAssistance.GnssSatelliteCorrections;
 import android.location.flags.Flags;
@@ -45,6 +44,9 @@
     /** The UTC model. */
     @Nullable private final UtcModel mUtcModel;
 
+    /** The auxiliary information. */
+    @Nullable private final AuxiliaryInformation mAuxiliaryInformation;
+
     /** The list of time models. */
     @NonNull private final List<TimeModel> mTimeModels;
 
@@ -57,6 +59,7 @@
     private GlonassAssistance(Builder builder) {
         mAlmanac = builder.mAlmanac;
         mUtcModel = builder.mUtcModel;
+        mAuxiliaryInformation = builder.mAuxiliaryInformation;
         if (builder.mTimeModels != null) {
             mTimeModels = Collections.unmodifiableList(new ArrayList<>(builder.mTimeModels));
         } else {
@@ -106,6 +109,12 @@
         return mSatelliteCorrections;
     }
 
+    /** Returns the auxiliary information. */
+    @Nullable
+    public AuxiliaryInformation getAuxiliaryInformation() {
+        return mAuxiliaryInformation;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -115,6 +124,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeTypedObject(mAlmanac, flags);
         dest.writeTypedObject(mUtcModel, flags);
+        dest.writeTypedObject(mAuxiliaryInformation, flags);
         dest.writeTypedList(mTimeModels);
         dest.writeTypedList(mSatelliteEphemeris);
         dest.writeTypedList(mSatelliteCorrections);
@@ -126,6 +136,7 @@
         StringBuilder builder = new StringBuilder("GlonassAssistance[");
         builder.append("almanac = ").append(mAlmanac);
         builder.append(", utcModel = ").append(mUtcModel);
+        builder.append(", auxiliaryInformation = ").append(mAuxiliaryInformation);
         builder.append(", timeModels = ").append(mTimeModels);
         builder.append(", satelliteEphemeris = ").append(mSatelliteEphemeris);
         builder.append(", satelliteCorrections = ").append(mSatelliteCorrections);
@@ -140,6 +151,8 @@
                     return new GlonassAssistance.Builder()
                             .setAlmanac(in.readTypedObject(GlonassAlmanac.CREATOR))
                             .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
+                            .setAuxiliaryInformation(
+                                    in.readTypedObject(AuxiliaryInformation.CREATOR))
                             .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
                             .setSatelliteEphemeris(
                                     in.createTypedArrayList(GlonassSatelliteEphemeris.CREATOR))
@@ -158,30 +171,36 @@
     public static final class Builder {
         private GlonassAlmanac mAlmanac;
         private UtcModel mUtcModel;
+        private AuxiliaryInformation mAuxiliaryInformation;
         private List<TimeModel> mTimeModels;
         private List<GlonassSatelliteEphemeris> mSatelliteEphemeris;
         private List<GnssSatelliteCorrections> mSatelliteCorrections;
 
         /** Sets the Glonass almanac. */
         @NonNull
-        public Builder setAlmanac(
-                @Nullable @SuppressLint("NullableCollection") GlonassAlmanac almanac) {
+        public Builder setAlmanac(@Nullable GlonassAlmanac almanac) {
             mAlmanac = almanac;
             return this;
         }
 
         /** Sets the UTC model. */
         @NonNull
-        public Builder setUtcModel(
-                @Nullable @SuppressLint("NullableCollection") UtcModel utcModel) {
+        public Builder setUtcModel(@Nullable UtcModel utcModel) {
             mUtcModel = utcModel;
             return this;
         }
 
+        /** Sets the auxiliary information. */
+        @NonNull
+        public Builder setAuxiliaryInformation(
+                @Nullable AuxiliaryInformation auxiliaryInformation) {
+            mAuxiliaryInformation = auxiliaryInformation;
+            return this;
+        }
+
         /** Sets the list of time models. */
         @NonNull
-        public Builder setTimeModels(
-                @Nullable @SuppressLint("NullableCollection") List<TimeModel> timeModels) {
+        public Builder setTimeModels(@NonNull List<TimeModel> timeModels) {
             mTimeModels = timeModels;
             return this;
         }
@@ -189,8 +208,7 @@
         /** Sets the list of Glonass satellite ephemeris. */
         @NonNull
         public Builder setSatelliteEphemeris(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GlonassSatelliteEphemeris> satelliteEphemeris) {
+                @NonNull List<GlonassSatelliteEphemeris> satelliteEphemeris) {
             mSatelliteEphemeris = satelliteEphemeris;
             return this;
         }
@@ -198,8 +216,7 @@
         /** Sets the list of Glonass satellite corrections. */
         @NonNull
         public Builder setSatelliteCorrections(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GnssSatelliteCorrections> satelliteCorrections) {
+                @NonNull List<GnssSatelliteCorrections> satelliteCorrections) {
             mSatelliteCorrections = satelliteCorrections;
             return this;
         }
diff --git a/location/java/android/location/GlonassSatelliteEphemeris.java b/location/java/android/location/GlonassSatelliteEphemeris.java
index 77a6ebb..bee6047 100644
--- a/location/java/android/location/GlonassSatelliteEphemeris.java
+++ b/location/java/android/location/GlonassSatelliteEphemeris.java
@@ -18,6 +18,7 @@
 
 import android.annotation.FlaggedApi;
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
@@ -27,6 +28,9 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A class contains ephemeris parameters specific to Glonass satellites.
  *
@@ -38,11 +42,31 @@
 @SystemApi
 public final class GlonassSatelliteEphemeris implements Parcelable {
 
+    /**
+     * Glonass signal health status.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({HEALTH_STATUS_HEALTHY, HEALTH_STATUS_UNHEALTHY})
+    public @interface GlonassHealthStatus {}
+
+    /**
+     * The following enumerations must be in sync with the values declared in
+     * GlonassSatelliteEphemeris.aidl
+     */
+
+    /** Health status is healthy. */
+    public static final int HEALTH_STATUS_HEALTHY = 0;
+
+    /** Health status is unhealthy. */
+    public static final int HEALTH_STATUS_UNHEALTHY = 1;
+
     /** L1/Satellite system (R), satellite number (slot number in sat. constellation). */
     private final int mSlotNumber;
 
-    /** Health state (0=healthy, 1=unhealthy). */
-    private final int mHealthState;
+    /** Health state. */
+    private final @GlonassHealthStatus int mHealthState;
 
     /** Message frame time in seconds of the UTC week (tk+nd*86400). */
     private final double mFrameTimeSeconds;
@@ -50,6 +74,15 @@
     /** Age of current information in days (E). */
     private final int mAgeInDays;
 
+    /** Update and validity interval in minutes (P1) */
+    private final int mUpdateIntervalMinutes;
+
+    /** Flag to indicate if the update interval is odd or even (P2). */
+    private final boolean mUpdateIntervalOdd;
+
+    /** Flag to indicates if the satellite is a Glonass-M satellitee (M). */
+    private final boolean mGlonassM;
+
     /** Satellite clock model. */
     @NonNull private final GlonassSatelliteClockModel mSatelliteClockModel;
 
@@ -63,6 +96,8 @@
         Preconditions.checkArgument(builder.mHealthState >= 0);
         Preconditions.checkArgument(builder.mFrameTimeSeconds >= 0.0f);
         Preconditions.checkArgumentInRange(builder.mAgeInDays, 0, 31, "AgeInDays");
+        Preconditions.checkArgumentInRange(
+                builder.mUpdateIntervalMinutes, 0, 60, "UpdateIntervalMinutes");
         Preconditions.checkNotNull(
                 builder.mSatelliteClockModel, "SatelliteClockModel cannot be null");
         Preconditions.checkNotNull(
@@ -71,6 +106,9 @@
         mHealthState = builder.mHealthState;
         mFrameTimeSeconds = builder.mFrameTimeSeconds;
         mAgeInDays = builder.mAgeInDays;
+        mUpdateIntervalMinutes = builder.mUpdateIntervalMinutes;
+        mUpdateIntervalOdd = builder.mUpdateIntervalOdd;
+        mGlonassM = builder.mGlonassM;
         mSatelliteClockModel = builder.mSatelliteClockModel;
         mSatelliteOrbitModel = builder.mSatelliteOrbitModel;
     }
@@ -83,9 +121,8 @@
         return mSlotNumber;
     }
 
-    /** Returns the health state (0=healthy, 1=unhealthy). */
-    @IntRange(from = 0, to = 1)
-    public int getHealthState() {
+    /** Returns the health state. */
+    public @GlonassHealthStatus int getHealthState() {
         return mHealthState;
     }
 
@@ -101,6 +138,22 @@
         return mAgeInDays;
     }
 
+    /** Returns the update interval in minutes (P1). */
+    @IntRange(from = 0, to = 60)
+    public int getUpdateIntervalMinutes() {
+        return mUpdateIntervalMinutes;
+    }
+
+    /** Returns true if the update interval (P2) is odd, false otherwise (P2). */
+    public boolean isUpdateIntervalOdd() {
+        return mUpdateIntervalOdd;
+    }
+
+    /** Returns true if the satellite is a Glonass-M satellitee (M), false otherwise. */
+    public boolean isGlonassM() {
+        return mGlonassM;
+    }
+
     /** Returns the satellite clock model. */
     @NonNull
     public GlonassSatelliteClockModel getSatelliteClockModel() {
@@ -124,6 +177,9 @@
         dest.writeInt(mHealthState);
         dest.writeDouble(mFrameTimeSeconds);
         dest.writeInt(mAgeInDays);
+        dest.writeInt(mUpdateIntervalMinutes);
+        dest.writeBoolean(mUpdateIntervalOdd);
+        dest.writeBoolean(mGlonassM);
         dest.writeTypedObject(mSatelliteClockModel, flags);
         dest.writeTypedObject(mSatelliteOrbitModel, flags);
     }
@@ -137,6 +193,9 @@
                             .setHealthState(source.readInt())
                             .setFrameTimeSeconds(source.readDouble())
                             .setAgeInDays(source.readInt())
+                            .setUpdateIntervalMinutes(source.readInt())
+                            .setUpdateIntervalOdd(source.readBoolean())
+                            .setGlonassM(source.readBoolean())
                             .setSatelliteClockModel(
                                     source.readTypedObject(GlonassSatelliteClockModel.CREATOR))
                             .setSatelliteOrbitModel(
@@ -158,6 +217,9 @@
         builder.append(", healthState = ").append(mHealthState);
         builder.append(", frameTimeSeconds = ").append(mFrameTimeSeconds);
         builder.append(", ageInDays = ").append(mAgeInDays);
+        builder.append(", updateIntervalMinutes = ").append(mUpdateIntervalMinutes);
+        builder.append(", isUpdateIntervalOdd = ").append(mUpdateIntervalOdd);
+        builder.append(", isGlonassM = ").append(mGlonassM);
         builder.append(", satelliteClockModel = ").append(mSatelliteClockModel);
         builder.append(", satelliteOrbitModel = ").append(mSatelliteOrbitModel);
         builder.append("]");
@@ -170,6 +232,9 @@
         private int mHealthState;
         private double mFrameTimeSeconds;
         private int mAgeInDays;
+        private int mUpdateIntervalMinutes;
+        private boolean mUpdateIntervalOdd;
+        private boolean mGlonassM;
         private GlonassSatelliteClockModel mSatelliteClockModel;
         private GlonassSatelliteOrbitModel mSatelliteOrbitModel;
 
@@ -182,9 +247,9 @@
             return this;
         }
 
-        /** Sets the health state (0=healthy, 1=unhealthy). */
+        /** Sets the health state. */
         @NonNull
-        public Builder setHealthState(@IntRange(from = 0, to = 1) int healthState) {
+        public Builder setHealthState(@GlonassHealthStatus int healthState) {
             mHealthState = healthState;
             return this;
         }
@@ -219,6 +284,28 @@
             return this;
         }
 
+        /** Sets the update interval in minutes (P1). */
+        @NonNull
+        public Builder setUpdateIntervalMinutes(
+                @IntRange(from = 0, to = 60) int updateIntervalMinutes) {
+            mUpdateIntervalMinutes = updateIntervalMinutes;
+            return this;
+        }
+
+        /** Sets to true if the update interval (P2) is odd, false otherwise. */
+        @NonNull
+        public Builder setUpdateIntervalOdd(boolean isUpdateIntervalOdd) {
+            mUpdateIntervalOdd = isUpdateIntervalOdd;
+            return this;
+        }
+
+        /** Sets to true if the satellite is a Glonass-M satellitee (M), false otherwise. */
+        @NonNull
+        public Builder setGlonassM(boolean isGlonassM) {
+            mGlonassM = isGlonassM;
+            return this;
+        }
+
         /** Builds a {@link GlonassSatelliteEphemeris}. */
         @NonNull
         public GlonassSatelliteEphemeris build() {
@@ -246,19 +333,36 @@
         /** Frequency bias (+GammaN). */
         private final double mFrequencyBias;
 
-        /** Frequency number. */
-        private final int mFrequencyNumber;
+        /** Frequency channel number. */
+        private final int mFrequencyChannelNumber;
+
+        /* L1/L2 group delay difference in seconds (DeltaTau). */
+        private final double mGroupDelayDiffSeconds;
+
+        /**
+         * Whether the L1/L2 group delay difference in seconds (DeltaTau) is available.
+         *
+         * <p>It is set to true if available, otherwise false.
+         */
+        private final boolean mGroupDelayDiffSecondsAvailable;
 
         private GlonassSatelliteClockModel(Builder builder) {
             Preconditions.checkArgument(builder.mTimeOfClockSeconds >= 0);
             Preconditions.checkArgumentInRange(builder.mClockBias, -0.002f, 0.002f, "ClockBias");
             Preconditions.checkArgumentInRange(
                     builder.mFrequencyBias, -9.32e-10f, 9.32e-10f, "FrequencyBias");
-            Preconditions.checkArgumentInRange(builder.mFrequencyNumber, -7, 6, "FrequencyNumber");
+            Preconditions.checkArgumentInRange(
+                    builder.mFrequencyChannelNumber, -7, 6, "FrequencyChannelNumber");
+            if (builder.mGroupDelayDiffSecondsAvailable) {
+                Preconditions.checkArgumentInRange(
+                        builder.mGroupDelayDiffSeconds, -1.4e-8f, 1.4e-8f, "GroupDelayDiffSeconds");
+            }
             mTimeOfClockSeconds = builder.mTimeOfClockSeconds;
             mClockBias = builder.mClockBias;
             mFrequencyBias = builder.mFrequencyBias;
-            mFrequencyNumber = builder.mFrequencyNumber;
+            mFrequencyChannelNumber = builder.mFrequencyChannelNumber;
+            mGroupDelayDiffSeconds = builder.mGroupDelayDiffSeconds;
+            mGroupDelayDiffSecondsAvailable = builder.mGroupDelayDiffSecondsAvailable;
         }
 
         /** Returns the time of clock in seconds (UTC). */
@@ -279,10 +383,21 @@
             return mFrequencyBias;
         }
 
-        /** Returns the frequency number. */
+        /** Returns the Frequency channel number. */
         @IntRange(from = -7, to = 6)
-        public int getFrequencyNumber() {
-            return mFrequencyNumber;
+        public int getFrequencyChannelNumber() {
+            return mFrequencyChannelNumber;
+        }
+
+        /** Returns the L1/L2 group delay difference in seconds (DeltaTau). */
+        @FloatRange(from = -1.4e-8f, to = 1.4e-8f)
+        public double getGroupDelayDiffSeconds() {
+            return mGroupDelayDiffSeconds;
+        }
+
+        /** Returns whether the L1/L2 group delay difference in seconds (DeltaTau) is available. */
+        public boolean isGroupDelayDiffSecondsAvailable() {
+            return mGroupDelayDiffSecondsAvailable;
         }
 
         @Override
@@ -295,7 +410,9 @@
             dest.writeLong(mTimeOfClockSeconds);
             dest.writeDouble(mClockBias);
             dest.writeDouble(mFrequencyBias);
-            dest.writeInt(mFrequencyNumber);
+            dest.writeInt(mFrequencyChannelNumber);
+            dest.writeDouble(mGroupDelayDiffSeconds);
+            dest.writeBoolean(mGroupDelayDiffSecondsAvailable);
         }
 
         public static final @NonNull Parcelable.Creator<GlonassSatelliteClockModel> CREATOR =
@@ -306,7 +423,9 @@
                                 .setTimeOfClockSeconds(source.readLong())
                                 .setClockBias(source.readDouble())
                                 .setFrequencyBias(source.readDouble())
-                                .setFrequencyNumber(source.readInt())
+                                .setFrequencyChannelNumber(source.readInt())
+                                .setGroupDelayDiffSeconds(source.readDouble())
+                                .setGroupDelayDiffSecondsAvailable(source.readBoolean())
                                 .build();
                     }
 
@@ -323,7 +442,10 @@
             builder.append("timeOfClockSeconds = ").append(mTimeOfClockSeconds);
             builder.append(", clockBias = ").append(mClockBias);
             builder.append(", frequencyBias = ").append(mFrequencyBias);
-            builder.append(", frequencyNumber = ").append(mFrequencyNumber);
+            builder.append(", frequencyChannelNumber = ").append(mFrequencyChannelNumber);
+            if (mGroupDelayDiffSecondsAvailable) {
+                builder.append(", groupDelayDiffSeconds = ").append(mGroupDelayDiffSeconds);
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -333,7 +455,9 @@
             private long mTimeOfClockSeconds;
             private double mClockBias;
             private double mFrequencyBias;
-            private int mFrequencyNumber;
+            private double mGroupDelayDiffSeconds;
+            private int mFrequencyChannelNumber;
+            private boolean mGroupDelayDiffSecondsAvailable;
 
             /** Sets the time of clock in seconds (UTC). */
             @NonNull
@@ -357,10 +481,27 @@
                 return this;
             }
 
-            /** Sets the frequency number. */
+            /** Sets the Frequency channel number. */
             @NonNull
-            public Builder setFrequencyNumber(@IntRange(from = -7, to = 6) int frequencyNumber) {
-                mFrequencyNumber = frequencyNumber;
+            public Builder setFrequencyChannelNumber(
+                    @IntRange(from = -7, to = 6) int frequencyChannelNumber) {
+                mFrequencyChannelNumber = frequencyChannelNumber;
+                return this;
+            }
+
+            /** Sets the L1/L2 group delay difference in seconds (DeltaTau). */
+            @NonNull
+            public Builder setGroupDelayDiffSeconds(
+                    @FloatRange(from = -1.4e-8f, to = 1.4e-8f) double groupDelayDiffSeconds) {
+                mGroupDelayDiffSeconds = groupDelayDiffSeconds;
+                return this;
+            }
+
+            /** Sets whether the L1/L2 group delay difference in seconds (DeltaTau) is available. */
+            @NonNull
+            public Builder setGroupDelayDiffSecondsAvailable(
+                    boolean isGroupDelayDiffSecondsAvailable) {
+                mGroupDelayDiffSecondsAvailable = isGroupDelayDiffSecondsAvailable;
                 return this;
             }
 
diff --git a/location/java/android/location/GnssAlmanac.java b/location/java/android/location/GnssAlmanac.java
index 6466e45a..c16ad91 100644
--- a/location/java/android/location/GnssAlmanac.java
+++ b/location/java/android/location/GnssAlmanac.java
@@ -59,7 +59,7 @@
      *
      * <p>This is unused for GPS/QZSS/Baidou.
      */
-    private final int mIod;
+    private final int mIoda;
 
     /**
      * Almanac reference week number.
@@ -75,20 +75,27 @@
     /** Almanac reference time in seconds. */
     private final int mToaSeconds;
 
+    /**
+     * Flag to indicate if the satelliteAlmanacs contains complete GNSS
+     * constellation indicated by svid.
+     */
+    private final boolean mCompleteAlmanacProvided;
+
     /** The list of GnssSatelliteAlmanacs. */
     @NonNull private final List<GnssSatelliteAlmanac> mGnssSatelliteAlmanacs;
 
     private GnssAlmanac(Builder builder) {
         Preconditions.checkArgument(builder.mIssueDateMillis >= 0);
-        Preconditions.checkArgument(builder.mIod >= 0);
+        Preconditions.checkArgument(builder.mIoda >= 0);
         Preconditions.checkArgument(builder.mWeekNumber >= 0);
         Preconditions.checkArgumentInRange(builder.mToaSeconds, 0, 604800, "ToaSeconds");
         Preconditions.checkNotNull(
                 builder.mGnssSatelliteAlmanacs, "GnssSatelliteAlmanacs cannot be null");
         mIssueDateMillis = builder.mIssueDateMillis;
-        mIod = builder.mIod;
+        mIoda = builder.mIoda;
         mWeekNumber = builder.mWeekNumber;
         mToaSeconds = builder.mToaSeconds;
+        mCompleteAlmanacProvided = builder.mCompleteAlmanacProvided;
         mGnssSatelliteAlmanacs =
                 Collections.unmodifiableList(new ArrayList<>(builder.mGnssSatelliteAlmanacs));
     }
@@ -101,8 +108,8 @@
 
     /** Returns the almanac issue of data. */
     @IntRange(from = 0)
-    public int getIod() {
-        return mIod;
+    public int getIoda() {
+        return mIoda;
     }
 
     /**
@@ -125,6 +132,14 @@
         return mToaSeconds;
     }
 
+    /**
+     * Returns the flag to indicate if the satelliteAlmanacs contains complete GNSS
+     * constellation indicated by svid.
+     */
+    public boolean isCompleteAlmanacProvided() {
+        return mCompleteAlmanacProvided;
+    }
+
     /** Returns the list of GnssSatelliteAlmanacs. */
     @NonNull
     public List<GnssSatelliteAlmanac> getGnssSatelliteAlmanacs() {
@@ -139,9 +154,10 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mIssueDateMillis);
-        dest.writeInt(mIod);
+        dest.writeInt(mIoda);
         dest.writeInt(mWeekNumber);
         dest.writeInt(mToaSeconds);
+        dest.writeBoolean(mCompleteAlmanacProvided);
         dest.writeTypedList(mGnssSatelliteAlmanacs);
     }
 
@@ -151,9 +167,10 @@
                 public GnssAlmanac createFromParcel(Parcel in) {
                     GnssAlmanac.Builder gnssAlmanac = new GnssAlmanac.Builder();
                     gnssAlmanac.setIssueDateMillis(in.readLong());
-                    gnssAlmanac.setIod(in.readInt());
+                    gnssAlmanac.setIoda(in.readInt());
                     gnssAlmanac.setWeekNumber(in.readInt());
                     gnssAlmanac.setToaSeconds(in.readInt());
+                    gnssAlmanac.setCompleteAlmanacProvided(in.readBoolean());
                     List<GnssSatelliteAlmanac> satelliteAlmanacs = new ArrayList<>();
                     in.readTypedList(satelliteAlmanacs, GnssSatelliteAlmanac.CREATOR);
                     gnssAlmanac.setGnssSatelliteAlmanacs(satelliteAlmanacs);
@@ -170,9 +187,10 @@
     public String toString() {
         StringBuilder builder = new StringBuilder("GnssAlmanac[");
         builder.append("issueDateMillis=").append(mIssueDateMillis);
-        builder.append(", iod=").append(mIod);
+        builder.append(", ioda=").append(mIoda);
         builder.append(", weekNumber=").append(mWeekNumber);
         builder.append(", toaSeconds=").append(mToaSeconds);
+        builder.append(", completeAlmanacProvided=").append(mCompleteAlmanacProvided);
         builder.append(", satelliteAlmanacs=").append(mGnssSatelliteAlmanacs);
         builder.append("]");
         return builder.toString();
@@ -181,9 +199,10 @@
     /** Builder for {@link GnssAlmanac}. */
     public static final class Builder {
         private long mIssueDateMillis;
-        private int mIod;
+        private int mIoda;
         private int mWeekNumber;
         private int mToaSeconds;
+        private boolean mCompleteAlmanacProvided;
         private List<GnssSatelliteAlmanac> mGnssSatelliteAlmanacs;
 
         /** Sets the almanac issue date in milliseconds (UTC). */
@@ -195,8 +214,8 @@
 
         /** Sets the almanac issue of data. */
         @NonNull
-        public Builder setIod(@IntRange(from = 0) int iod) {
-            mIod = iod;
+        public Builder setIoda(@IntRange(from = 0) int ioda) {
+            mIoda = ioda;
             return this;
         }
 
@@ -222,6 +241,16 @@
             return this;
         }
 
+        /**
+         * Sets to true if the satelliteAlmanacs contains complete GNSS
+         * constellation indicated by svid, false otherwise.
+         */
+        @NonNull
+        public Builder setCompleteAlmanacProvided(boolean isCompleteAlmanacProvided) {
+            this.mCompleteAlmanacProvided = isCompleteAlmanacProvided;
+            return this;
+        }
+
         /** Sets the list of GnssSatelliteAlmanacs. */
         @NonNull
         public Builder setGnssSatelliteAlmanacs(
@@ -249,7 +278,7 @@
      * <p>For Galileo, this is defined in Galileo-OS-SIS-ICD-v2.1 section 5.1.10.
      */
     public static final class GnssSatelliteAlmanac implements Parcelable {
-        /** The PRN number of the GNSS satellite. */
+        /** The PRN or satellite ID number for the GNSS satellite. */
         private final int mSvid;
 
         /**
@@ -332,7 +361,7 @@
             mAf1 = builder.mAf1;
         }
 
-        /** Returns the PRN number of the GNSS satellite. */
+        /** Returns the PRN or satellite ID number of the GNSS satellite. */
         @IntRange(from = 1)
         public int getSvid() {
             return mSvid;
@@ -503,7 +532,7 @@
             private double mAf0;
             private double mAf1;
 
-            /** Sets the PRN number of the GNSS satellite. */
+            /** Sets the PRN or satellite ID number of the GNSS satellite. */
             @NonNull
             public Builder setSvid(@IntRange(from = 1) int svid) {
                 mSvid = svid;
diff --git a/location/java/android/location/GpsAssistance.java b/location/java/android/location/GpsAssistance.java
index 5202fc4..5a8802f 100644
--- a/location/java/android/location/GpsAssistance.java
+++ b/location/java/android/location/GpsAssistance.java
@@ -51,6 +51,9 @@
     /** The leap seconds model. */
     @Nullable private final LeapSecondsModel mLeapSecondsModel;
 
+    /** The auxiliary information. */
+    @Nullable private final AuxiliaryInformation mAuxiliaryInformation;
+
     /** The list of time models. */
     @NonNull private final List<TimeModel> mTimeModels;
 
@@ -68,6 +71,7 @@
         mIonosphericModel = builder.mIonosphericModel;
         mUtcModel = builder.mUtcModel;
         mLeapSecondsModel = builder.mLeapSecondsModel;
+        mAuxiliaryInformation = builder.mAuxiliaryInformation;
         if (builder.mTimeModels != null) {
             mTimeModels = Collections.unmodifiableList(new ArrayList<>(builder.mTimeModels));
         } else {
@@ -117,6 +121,12 @@
         return mLeapSecondsModel;
     }
 
+    /** Returns the auxiliary information. */
+    @Nullable
+    public AuxiliaryInformation getAuxiliaryInformation() {
+        return mAuxiliaryInformation;
+    }
+
     /** Returns the list of time models. */
     @NonNull
     public List<TimeModel> getTimeModels() {
@@ -152,6 +162,8 @@
                                     in.readTypedObject(KlobucharIonosphericModel.CREATOR))
                             .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
                             .setLeapSecondsModel(in.readTypedObject(LeapSecondsModel.CREATOR))
+                            .setAuxiliaryInformation(
+                                    in.readTypedObject(AuxiliaryInformation.CREATOR))
                             .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
                             .setSatelliteEphemeris(
                                     in.createTypedArrayList(GpsSatelliteEphemeris.CREATOR))
@@ -179,6 +191,7 @@
         dest.writeTypedObject(mIonosphericModel, flags);
         dest.writeTypedObject(mUtcModel, flags);
         dest.writeTypedObject(mLeapSecondsModel, flags);
+        dest.writeTypedObject(mAuxiliaryInformation, flags);
         dest.writeTypedList(mTimeModels);
         dest.writeTypedList(mSatelliteEphemeris);
         dest.writeTypedList(mRealTimeIntegrityModels);
@@ -193,6 +206,7 @@
         builder.append(", ionosphericModel = ").append(mIonosphericModel);
         builder.append(", utcModel = ").append(mUtcModel);
         builder.append(", leapSecondsModel = ").append(mLeapSecondsModel);
+        builder.append(", auxiliaryInformation = ").append(mAuxiliaryInformation);
         builder.append(", timeModels = ").append(mTimeModels);
         builder.append(", satelliteEphemeris = ").append(mSatelliteEphemeris);
         builder.append(", realTimeIntegrityModels = ").append(mRealTimeIntegrityModels);
@@ -207,6 +221,7 @@
         private KlobucharIonosphericModel mIonosphericModel;
         private UtcModel mUtcModel;
         private LeapSecondsModel mLeapSecondsModel;
+        private AuxiliaryInformation mAuxiliaryInformation;
         private List<TimeModel> mTimeModels;
         private List<GpsSatelliteEphemeris> mSatelliteEphemeris;
         private List<RealTimeIntegrityModel> mRealTimeIntegrityModels;
@@ -222,33 +237,36 @@
 
         /** Sets the Klobuchar ionospheric model. */
         @NonNull
-        public Builder setIonosphericModel(
-                @Nullable @SuppressLint("NullableCollection")
-                        KlobucharIonosphericModel ionosphericModel) {
+        public Builder setIonosphericModel(@Nullable KlobucharIonosphericModel ionosphericModel) {
             mIonosphericModel = ionosphericModel;
             return this;
         }
 
         /** Sets the UTC model. */
         @NonNull
-        public Builder setUtcModel(
-                @Nullable @SuppressLint("NullableCollection") UtcModel utcModel) {
+        public Builder setUtcModel(@Nullable UtcModel utcModel) {
             mUtcModel = utcModel;
             return this;
         }
 
         /** Sets the leap seconds model. */
         @NonNull
-        public Builder setLeapSecondsModel(
-                @Nullable @SuppressLint("NullableCollection") LeapSecondsModel leapSecondsModel) {
+        public Builder setLeapSecondsModel(@Nullable LeapSecondsModel leapSecondsModel) {
             mLeapSecondsModel = leapSecondsModel;
             return this;
         }
 
+        /** Sets the auxiliary information. */
+        @NonNull
+        public Builder setAuxiliaryInformation(
+                @Nullable AuxiliaryInformation auxiliaryInformation) {
+            mAuxiliaryInformation = auxiliaryInformation;
+            return this;
+        }
+
         /** Sets the list of time models. */
         @NonNull
-        public Builder setTimeModels(
-                @Nullable @SuppressLint("NullableCollection") List<TimeModel> timeModels) {
+        public Builder setTimeModels(@NonNull List<TimeModel> timeModels) {
             mTimeModels = timeModels;
             return this;
         }
@@ -256,8 +274,7 @@
         /** Sets the list of GPS ephemeris. */
         @NonNull
         public Builder setSatelliteEphemeris(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GpsSatelliteEphemeris> satelliteEphemeris) {
+                @NonNull List<GpsSatelliteEphemeris> satelliteEphemeris) {
             mSatelliteEphemeris = satelliteEphemeris;
             return this;
         }
@@ -265,8 +282,7 @@
         /** Sets the list of real time integrity models. */
         @NonNull
         public Builder setRealTimeIntegrityModels(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<RealTimeIntegrityModel> realTimeIntegrityModels) {
+                @NonNull List<RealTimeIntegrityModel> realTimeIntegrityModels) {
             mRealTimeIntegrityModels = realTimeIntegrityModels;
             return this;
         }
@@ -274,8 +290,7 @@
         /** Sets the list of GPS satellite corrections. */
         @NonNull
         public Builder setSatelliteCorrections(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GnssSatelliteCorrections> satelliteCorrections) {
+                @NonNull List<GnssSatelliteCorrections> satelliteCorrections) {
             mSatelliteCorrections = satelliteCorrections;
             return this;
         }
diff --git a/location/java/android/location/GpsSatelliteEphemeris.java b/location/java/android/location/GpsSatelliteEphemeris.java
index ec6bc59..0abdc30d 100644
--- a/location/java/android/location/GpsSatelliteEphemeris.java
+++ b/location/java/android/location/GpsSatelliteEphemeris.java
@@ -37,8 +37,8 @@
 @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
 @SystemApi
 public final class GpsSatelliteEphemeris implements Parcelable {
-    /** Satellite PRN */
-    private final int mPrn;
+    /** PRN or satellite ID number for the GPS satellite. */
+    private final int mSvid;
 
     /** L2 parameters. */
     @NonNull private final GpsL2Params mGpsL2Params;
@@ -56,8 +56,8 @@
     @NonNull private final SatelliteEphemerisTime mSatelliteEphemerisTime;
 
     private GpsSatelliteEphemeris(Builder builder) {
-        // Allow PRN beyond the range to support potential future extensibility.
-        Preconditions.checkArgument(builder.mPrn >= 1);
+        // Allow svid beyond the range to support potential future extensibility.
+        Preconditions.checkArgument(builder.mSvid >= 1);
         Preconditions.checkNotNull(builder.mGpsL2Params, "GPSL2Params cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteClockModel,
                 "SatelliteClockModel cannot be null");
@@ -67,7 +67,7 @@
                 "SatelliteHealth cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteEphemerisTime,
                 "SatelliteEphemerisTime cannot be null");
-        mPrn = builder.mPrn;
+        mSvid = builder.mSvid;
         mGpsL2Params = builder.mGpsL2Params;
         mSatelliteClockModel = builder.mSatelliteClockModel;
         mSatelliteOrbitModel = builder.mSatelliteOrbitModel;
@@ -75,10 +75,10 @@
         mSatelliteEphemerisTime = builder.mSatelliteEphemerisTime;
     }
 
-    /** Returns the PRN of the satellite. */
+    /** Returns the svid of the satellite. */
     @IntRange(from = 1, to = 32)
-    public int getPrn() {
-        return mPrn;
+    public int getSvid() {
+        return mSvid;
     }
 
     /** Returns the L2 parameters of the satellite. */
@@ -118,7 +118,7 @@
                 public GpsSatelliteEphemeris createFromParcel(Parcel in) {
                     final GpsSatelliteEphemeris.Builder gpsSatelliteEphemeris =
                             new Builder()
-                                    .setPrn(in.readInt())
+                                    .setSvid(in.readInt())
                                     .setGpsL2Params(in.readTypedObject(GpsL2Params.CREATOR))
                                     .setSatelliteClockModel(
                                             in.readTypedObject(GpsSatelliteClockModel.CREATOR))
@@ -144,7 +144,7 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
-        parcel.writeInt(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeTypedObject(mGpsL2Params, flags);
         parcel.writeTypedObject(mSatelliteClockModel, flags);
         parcel.writeTypedObject(mSatelliteOrbitModel, flags);
@@ -156,7 +156,7 @@
     @NonNull
     public String toString() {
         StringBuilder builder = new StringBuilder("GpsSatelliteEphemeris[");
-        builder.append("prn = ").append(mPrn);
+        builder.append("Svid = ").append(mSvid);
         builder.append(", gpsL2Params = ").append(mGpsL2Params);
         builder.append(", satelliteClockModel = ").append(mSatelliteClockModel);
         builder.append(", satelliteOrbitModel = ").append(mSatelliteOrbitModel);
@@ -168,17 +168,17 @@
 
     /** Builder for {@link GpsSatelliteEphemeris} */
     public static final class Builder {
-        private int mPrn = 0;
+        private int mSvid = 0;
         private GpsL2Params mGpsL2Params;
         private GpsSatelliteClockModel mSatelliteClockModel;
         private KeplerianOrbitModel mSatelliteOrbitModel;
         private GpsSatelliteHealth mSatelliteHealth;
         private SatelliteEphemerisTime mSatelliteEphemerisTime;
 
-        /** Sets the PRN of the satellite. */
+        /** Sets the PRN or satellite ID number for the GPS satellite.. */
         @NonNull
-        public Builder setPrn(@IntRange(from = 1, to = 32) int prn) {
-            mPrn = prn;
+        public Builder setSvid(@IntRange(from = 1, to = 32) int svid) {
+            mSvid = svid;
             return this;
         }
 
diff --git a/location/java/android/location/QzssAssistance.java b/location/java/android/location/QzssAssistance.java
index 9383ce3..27c3437 100644
--- a/location/java/android/location/QzssAssistance.java
+++ b/location/java/android/location/QzssAssistance.java
@@ -19,7 +19,6 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.location.GnssAssistance.GnssSatelliteCorrections;
 import android.location.flags.Flags;
@@ -51,6 +50,9 @@
     /** The leap seconds model. */
     @Nullable private final LeapSecondsModel mLeapSecondsModel;
 
+    /** The auxiliary information. */
+    @Nullable private final AuxiliaryInformation mAuxiliaryInformation;
+
     /** The list of time models. */
     @NonNull private final List<TimeModel> mTimeModels;
 
@@ -68,6 +70,7 @@
         mIonosphericModel = builder.mIonosphericModel;
         mUtcModel = builder.mUtcModel;
         mLeapSecondsModel = builder.mLeapSecondsModel;
+        mAuxiliaryInformation = builder.mAuxiliaryInformation;
         if (builder.mTimeModels != null) {
             mTimeModels = Collections.unmodifiableList(new ArrayList<>(builder.mTimeModels));
         } else {
@@ -117,6 +120,12 @@
         return mLeapSecondsModel;
     }
 
+    /** Returns the auxiliary information. */
+    @Nullable
+    public AuxiliaryInformation getAuxiliaryInformation() {
+        return mAuxiliaryInformation;
+    }
+
     /** Returns the list of time models. */
     @NonNull
     public List<TimeModel> getTimeModels() {
@@ -147,19 +156,23 @@
                 @NonNull
                 public QzssAssistance createFromParcel(Parcel in) {
                     return new QzssAssistance.Builder()
-                        .setAlmanac(in.readTypedObject(GnssAlmanac.CREATOR))
-                        .setIonosphericModel(in.readTypedObject(KlobucharIonosphericModel.CREATOR))
-                        .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
-                        .setLeapSecondsModel(in.readTypedObject(LeapSecondsModel.CREATOR))
-                        .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
-                        .setSatelliteEphemeris(
-                                in.createTypedArrayList(QzssSatelliteEphemeris.CREATOR))
-                        .setRealTimeIntegrityModels(
-                                in.createTypedArrayList(RealTimeIntegrityModel.CREATOR))
-                        .setSatelliteCorrections(
-                                in.createTypedArrayList(GnssSatelliteCorrections.CREATOR))
-                        .build();
+                            .setAlmanac(in.readTypedObject(GnssAlmanac.CREATOR))
+                            .setIonosphericModel(
+                                    in.readTypedObject(KlobucharIonosphericModel.CREATOR))
+                            .setUtcModel(in.readTypedObject(UtcModel.CREATOR))
+                            .setLeapSecondsModel(in.readTypedObject(LeapSecondsModel.CREATOR))
+                            .setAuxiliaryInformation(
+                                    in.readTypedObject(AuxiliaryInformation.CREATOR))
+                            .setTimeModels(in.createTypedArrayList(TimeModel.CREATOR))
+                            .setSatelliteEphemeris(
+                                    in.createTypedArrayList(QzssSatelliteEphemeris.CREATOR))
+                            .setRealTimeIntegrityModels(
+                                    in.createTypedArrayList(RealTimeIntegrityModel.CREATOR))
+                            .setSatelliteCorrections(
+                                    in.createTypedArrayList(GnssSatelliteCorrections.CREATOR))
+                            .build();
                 }
+
                 @Override
                 public QzssAssistance[] newArray(int size) {
                     return new QzssAssistance[size];
@@ -177,6 +190,7 @@
         dest.writeTypedObject(mIonosphericModel, flags);
         dest.writeTypedObject(mUtcModel, flags);
         dest.writeTypedObject(mLeapSecondsModel, flags);
+        dest.writeTypedObject(mAuxiliaryInformation, flags);
         dest.writeTypedList(mTimeModels);
         dest.writeTypedList(mSatelliteEphemeris);
         dest.writeTypedList(mRealTimeIntegrityModels);
@@ -191,6 +205,7 @@
         builder.append(", ionosphericModel = ").append(mIonosphericModel);
         builder.append(", utcModel = ").append(mUtcModel);
         builder.append(", leapSecondsModel = ").append(mLeapSecondsModel);
+        builder.append(", auxiliaryInformation = ").append(mAuxiliaryInformation);
         builder.append(", timeModels = ").append(mTimeModels);
         builder.append(", satelliteEphemeris = ").append(mSatelliteEphemeris);
         builder.append(", realTimeIntegrityModels = ").append(mRealTimeIntegrityModels);
@@ -205,6 +220,7 @@
         private KlobucharIonosphericModel mIonosphericModel;
         private UtcModel mUtcModel;
         private LeapSecondsModel mLeapSecondsModel;
+        private AuxiliaryInformation mAuxiliaryInformation;
         private List<TimeModel> mTimeModels;
         private List<QzssSatelliteEphemeris> mSatelliteEphemeris;
         private List<RealTimeIntegrityModel> mRealTimeIntegrityModels;
@@ -238,10 +254,17 @@
             return this;
         }
 
+        /** Sets the auxiliary information. */
+        @NonNull
+        public Builder setAuxiliaryInformation(
+                @Nullable AuxiliaryInformation auxiliaryInformation) {
+            mAuxiliaryInformation = auxiliaryInformation;
+            return this;
+        }
+
         /** Sets the list of time models. */
         @NonNull
-        public Builder setTimeModels(
-                @Nullable @SuppressLint("NullableCollection") List<TimeModel> timeModels) {
+        public Builder setTimeModels(@NonNull List<TimeModel> timeModels) {
             mTimeModels = timeModels;
             return this;
         }
@@ -249,8 +272,7 @@
         /** Sets the list of QZSS ephemeris. */
         @NonNull
         public Builder setSatelliteEphemeris(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<QzssSatelliteEphemeris> satelliteEphemeris) {
+                @NonNull List<QzssSatelliteEphemeris> satelliteEphemeris) {
             mSatelliteEphemeris = satelliteEphemeris;
             return this;
         }
@@ -258,8 +280,7 @@
         /** Sets the list of real time integrity model. */
         @NonNull
         public Builder setRealTimeIntegrityModels(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<RealTimeIntegrityModel> realTimeIntegrityModels) {
+                @NonNull List<RealTimeIntegrityModel> realTimeIntegrityModels) {
             mRealTimeIntegrityModels = realTimeIntegrityModels;
             return this;
         }
@@ -267,8 +288,7 @@
         /** Sets the list of QZSS satellite correction. */
         @NonNull
         public Builder setSatelliteCorrections(
-                @Nullable @SuppressLint("NullableCollection")
-                        List<GnssSatelliteCorrections> satelliteCorrections) {
+                @NonNull List<GnssSatelliteCorrections> satelliteCorrections) {
             mSatelliteCorrections = satelliteCorrections;
             return this;
         }
diff --git a/location/java/android/location/QzssSatelliteEphemeris.java b/location/java/android/location/QzssSatelliteEphemeris.java
index 96203d9..dd9f408 100644
--- a/location/java/android/location/QzssSatelliteEphemeris.java
+++ b/location/java/android/location/QzssSatelliteEphemeris.java
@@ -39,8 +39,8 @@
 @FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
 @SystemApi
 public final class QzssSatelliteEphemeris implements Parcelable {
-    /** Satellite PRN. */
-    private final int mPrn;
+    /** PRN or satellite ID number for the Qzss satellite. */
+    private final int mSvid;
 
     /** L2 parameters. */
     @NonNull private final GpsL2Params mGpsL2Params;
@@ -57,10 +57,10 @@
     /** Ephemeris time. */
     @NonNull private final SatelliteEphemerisTime mSatelliteEphemerisTime;
 
-    /** Returns the PRN of the satellite. */
+    /** Returns the PRN or satellite ID number for the Qzss satellite. */
     @IntRange(from = 183, to = 206)
-    public int getPrn() {
-        return mPrn;
+    public int getSvid() {
+        return mSvid;
     }
 
     /** Returns the L2 parameters of the satellite. */
@@ -95,7 +95,7 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
-        parcel.writeInt(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeTypedObject(mGpsL2Params, flags);
         parcel.writeTypedObject(mSatelliteClockModel, flags);
         parcel.writeTypedObject(mSatelliteOrbitModel, flags);
@@ -104,8 +104,8 @@
     }
 
     private QzssSatelliteEphemeris(Builder builder) {
-        // Allow PRN beyond the range to support potential future extensibility.
-        Preconditions.checkArgument(builder.mPrn >= 1);
+        // Allow Svid beyond the range to support potential future extensibility.
+        Preconditions.checkArgument(builder.mSvid >= 1);
         Preconditions.checkNotNull(builder.mGpsL2Params, "GpsL2Params cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteClockModel,
                 "SatelliteClockModel cannot be null");
@@ -115,7 +115,7 @@
                 "SatelliteHealth cannot be null");
         Preconditions.checkNotNull(builder.mSatelliteEphemerisTime,
                 "SatelliteEphemerisTime cannot be null");
-        mPrn = builder.mPrn;
+        mSvid = builder.mSvid;
         mGpsL2Params = builder.mGpsL2Params;
         mSatelliteClockModel = builder.mSatelliteClockModel;
         mSatelliteOrbitModel = builder.mSatelliteOrbitModel;
@@ -130,7 +130,7 @@
                 public QzssSatelliteEphemeris createFromParcel(Parcel in) {
                     final QzssSatelliteEphemeris.Builder qzssSatelliteEphemeris =
                             new Builder()
-                                    .setPrn(in.readInt())
+                                    .setSvid(in.readInt())
                                     .setGpsL2Params(in.readTypedObject(GpsL2Params.CREATOR))
                                     .setSatelliteClockModel(
                                             in.readTypedObject(GpsSatelliteClockModel.CREATOR))
@@ -158,7 +158,7 @@
     @NonNull
     public String toString() {
         StringBuilder builder = new StringBuilder("QzssSatelliteEphemeris[");
-        builder.append("prn=").append(mPrn);
+        builder.append("Svid=").append(mSvid);
         builder.append(", gpsL2Params=").append(mGpsL2Params);
         builder.append(", satelliteClockModel=").append(mSatelliteClockModel);
         builder.append(", satelliteOrbitModel=").append(mSatelliteOrbitModel);
@@ -170,17 +170,17 @@
 
     /** Builder for {@link QzssSatelliteEphemeris}. */
     public static final class Builder {
-        private int mPrn;
+        private int mSvid;
         private GpsL2Params mGpsL2Params;
         private GpsSatelliteClockModel mSatelliteClockModel;
         private KeplerianOrbitModel mSatelliteOrbitModel;
         private GpsSatelliteHealth mSatelliteHealth;
         private SatelliteEphemerisTime mSatelliteEphemerisTime;
 
-        /** Sets the PRN of the satellite. */
+        /** Sets the PRN or satellite ID number for the Qzss satellite. */
         @NonNull
-        public Builder setPrn(@IntRange(from = 183, to = 206) int prn) {
-            mPrn = prn;
+        public Builder setSvid(@IntRange(from = 183, to = 206) int svid) {
+            mSvid = svid;
             return this;
         }
 
diff --git a/location/java/android/location/RealTimeIntegrityModel.java b/location/java/android/location/RealTimeIntegrityModel.java
index d268926..f065def 100644
--- a/location/java/android/location/RealTimeIntegrityModel.java
+++ b/location/java/android/location/RealTimeIntegrityModel.java
@@ -26,6 +26,10 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A class contains the real time integrity status of a GNSS satellite based on notice advisory.
  *
@@ -35,8 +39,7 @@
 @SystemApi
 public final class RealTimeIntegrityModel implements Parcelable {
     /**
-     * Pseudo-random or satellite ID number for the satellite,
-     * a.k.a. Space Vehicle (SV), or OSN number for Glonass.
+     * Bad satellite ID number or OSN number for Glonass.
      *
      * <p>The distinction is made by looking at the constellation field. Values
      * must be in the range of:
@@ -47,10 +50,14 @@
      * <p> - Galileo: 1-36
      * <p> - Beidou: 1-63
      */
-    private final int mSvid;
+    private final int mBadSvid;
 
-    /** Indicates whether the satellite is currently usable for navigation. */
-    private final boolean mUsable;
+    /**
+     * The type of the bad signal or signals.
+     *
+     * <p>An empty list means that all signals on the specific SV are not healthy.
+     */
+    @NonNull private final List<GnssSignalType> mBadSignalTypes;
 
     /** UTC timestamp (in seconds) when the advisory was published. */
     private final long mPublishDateSeconds;
@@ -81,14 +88,19 @@
 
     private RealTimeIntegrityModel(Builder builder) {
         // Allow SV ID beyond the range to support potential future extensibility.
-        Preconditions.checkArgument(builder.mSvid >= 1);
+        Preconditions.checkArgument(builder.mBadSvid >= 1);
         Preconditions.checkArgument(builder.mPublishDateSeconds > 0);
         Preconditions.checkArgument(builder.mStartDateSeconds > 0);
         Preconditions.checkArgument(builder.mEndDateSeconds > 0);
         Preconditions.checkNotNull(builder.mAdvisoryType, "AdvisoryType cannot be null");
         Preconditions.checkNotNull(builder.mAdvisoryNumber, "AdvisoryNumber cannot be null");
-        mSvid = builder.mSvid;
-        mUsable = builder.mUsable;
+        if (builder.mBadSignalTypes == null) {
+            mBadSignalTypes = new ArrayList<>();
+        } else {
+            mBadSignalTypes = Collections.unmodifiableList(
+                new ArrayList<>(builder.mBadSignalTypes));
+        }
+        mBadSvid = builder.mBadSvid;
         mPublishDateSeconds = builder.mPublishDateSeconds;
         mStartDateSeconds = builder.mStartDateSeconds;
         mEndDateSeconds = builder.mEndDateSeconds;
@@ -110,13 +122,18 @@
      * <p> - Beidou: 1-63
      */
     @IntRange(from = 1, to = 206)
-    public int getSvid() {
-        return mSvid;
+    public int getBadSvid() {
+        return mBadSvid;
     }
 
-    /** Returns whether the satellite is usable or not. */
-    public boolean isUsable() {
-        return mUsable;
+    /**
+     * Returns the type of the bad signal or signals.
+     *
+     * <p>An empty list means that all signals on the specific SV are not healthy.
+     */
+    @NonNull
+    public List<GnssSignalType> getBadSignalTypes() {
+        return mBadSignalTypes;
     }
 
     /** Returns the UTC timestamp (in seconds) when the advisory was published */
@@ -156,8 +173,9 @@
                 public RealTimeIntegrityModel createFromParcel(Parcel in) {
                     RealTimeIntegrityModel realTimeIntegrityModel =
                             new RealTimeIntegrityModel.Builder()
-                                    .setSvid(in.readInt())
-                                    .setUsable(in.readBoolean())
+                                    .setBadSvid(in.readInt())
+                                    .setBadSignalTypes(
+                                      in.createTypedArrayList(GnssSignalType.CREATOR))
                                     .setPublishDateSeconds(in.readLong())
                                     .setStartDateSeconds(in.readLong())
                                     .setEndDateSeconds(in.readLong())
@@ -180,8 +198,8 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
-        parcel.writeInt(mSvid);
-        parcel.writeBoolean(mUsable);
+        parcel.writeInt(mBadSvid);
+        parcel.writeTypedList(mBadSignalTypes);
         parcel.writeLong(mPublishDateSeconds);
         parcel.writeLong(mStartDateSeconds);
         parcel.writeLong(mEndDateSeconds);
@@ -193,8 +211,8 @@
     @NonNull
     public String toString() {
         StringBuilder builder = new StringBuilder("RealTimeIntegrityModel[");
-        builder.append("svid = ").append(mSvid);
-        builder.append(", usable = ").append(mUsable);
+        builder.append("badSvid = ").append(mBadSvid);
+        builder.append(", badSignalTypes = ").append(mBadSignalTypes);
         builder.append(", publishDateSeconds = ").append(mPublishDateSeconds);
         builder.append(", startDateSeconds = ").append(mStartDateSeconds);
         builder.append(", endDateSeconds = ").append(mEndDateSeconds);
@@ -206,8 +224,8 @@
 
     /** Builder for {@link RealTimeIntegrityModel} */
     public static final class Builder {
-        private int mSvid;
-        private boolean mUsable;
+        private int mBadSvid;
+        private List<GnssSignalType> mBadSignalTypes;
         private long mPublishDateSeconds;
         private long mStartDateSeconds;
         private long mEndDateSeconds;
@@ -215,8 +233,7 @@
         private String mAdvisoryNumber;
 
         /**
-         * Sets the Pseudo-random or satellite ID number for the satellite,
-         * a.k.a. Space Vehicle (SV), or OSN number for Glonass.
+         * Sets the bad satellite ID number or OSN number for Glonass.
          *
          * <p>The distinction is made by looking at the constellation field. Values
          * must be in the range of:
@@ -228,15 +245,19 @@
          * <p> - Beidou: 1-63
          */
         @NonNull
-        public Builder setSvid(@IntRange(from = 1, to = 206) int svid) {
-            mSvid = svid;
+        public Builder setBadSvid(@IntRange(from = 1, to = 206) int badSvid) {
+            mBadSvid = badSvid;
             return this;
         }
 
-        /** Sets whether the satellite is usable or not. */
+        /**
+         * Sets the type of the bad signal or signals.
+         *
+         * <p>An empty list means that all signals on the specific SV are not healthy.
+         */
         @NonNull
-        public Builder setUsable(boolean usable) {
-            mUsable = usable;
+        public Builder setBadSignalTypes(@NonNull List<GnssSignalType> badSignalTypes) {
+            mBadSignalTypes = badSignalTypes;
             return this;
         }
 
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index c02cc80..1b38982 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -167,4 +167,4 @@
     namespace: "location"
     description: "Flag for GNSS assistance interface"
     bug: "209078566"
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/provider/GnssAssistanceProviderBase.java b/location/java/android/location/provider/GnssAssistanceProviderBase.java
new file mode 100644
index 0000000..f4b26d5
--- /dev/null
+++ b/location/java/android/location/provider/GnssAssistanceProviderBase.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location.provider;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.content.Intent;
+import android.location.GnssAssistance;
+import android.location.flags.Flags;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.OutcomeReceiver;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+/**
+ * Base class for GNSS assistance providers outside the system server.
+ *
+ * <p>GNSS assistance providers should be wrapped in a non-exported service which returns the result
+ * of {@link #getBinder()} from the service's {@link android.app.Service#onBind(Intent)} method. The
+ * service should not be exported so that components other than the system server cannot bind to it.
+ * Alternatively, the service may be guarded by a permission that only system server can obtain. The
+ * service may specify metadata on its capabilities:
+ *
+ * <ul>
+ *   <li>"serviceVersion": An integer version code to help tie break if multiple services are
+ *       capable of implementing the geocode provider. All else equal, the service with the highest
+ *       version code will be chosen. Assumed to be 0 if not specified.
+ *   <li>"serviceIsMultiuser": A boolean property, indicating if the service wishes to take
+ *       responsibility for handling changes to the current user on the device. If true, the service
+ *       will always be bound from the system user. If false, the service will always be bound from
+ *       the current user. If the current user changes, the old binding will be released, and a new
+ *       binding established under the new user. Assumed to be false if not specified.
+ * </ul>
+ *
+ * <p>The service should have an intent filter in place for the GNSS assistance provider as
+ * specified by the constant in this class.
+ *
+ * <p>GNSS assistance providers are identified by their UID / package name / attribution tag. Based
+ * on this identity, geocode providers may be given some special privileges.
+ *
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
+@SystemApi
+public abstract class GnssAssistanceProviderBase {
+
+    /**
+     * The action the wrapping service should have in its intent filter to implement the GNSS
+     * Assistance provider.
+     */
+    public static final String ACTION_GNSS_ASSISTANCE_PROVIDER =
+            "android.location.provider.action.GNSS_ASSISTANCE_PROVIDER";
+
+    final String mTag;
+    @Nullable
+    final String mAttributionTag;
+    final IBinder mBinder;
+
+    /**
+     * Subclasses should pass in a context and an arbitrary tag that may be used for logcat logging
+     * of errors, and thus should uniquely identify the class.
+     */
+    public GnssAssistanceProviderBase(@NonNull Context context, @NonNull String tag) {
+        mTag = tag;
+        mAttributionTag = context.getAttributionTag();
+        mBinder = new GnssAssistanceProviderBase.Service();
+    }
+
+    /**
+     * Returns the IBinder instance that should be returned from the {@link
+     * android.app.Service#onBind(Intent)} method of the wrapping service.
+     */
+    @NonNull
+    public final IBinder getBinder() {
+        return mBinder;
+    }
+
+    /**
+     * Requests GNSS assistance data of the given arguments. The given callback must be invoked
+     * once.
+     */
+    public abstract void onRequest(
+            @NonNull OutcomeReceiver<GnssAssistance, Throwable> callback);
+
+    private class Service extends IGnssAssistanceProvider.Stub {
+        @Override
+        public void request(IGnssAssistanceCallback callback) {
+            try {
+                onRequest(new GnssAssistanceProviderBase.SingleUseCallback(callback));
+            } catch (RuntimeException e) {
+                // exceptions on one-way binder threads are dropped - move to a different thread
+                Log.w(mTag, e);
+                new Handler(Looper.getMainLooper())
+                        .post(
+                                () -> {
+                                    throw new AssertionError(e);
+                                });
+            }
+        }
+    }
+
+    private static class SingleUseCallback implements
+            OutcomeReceiver<GnssAssistance, Throwable> {
+
+        private final AtomicReference<IGnssAssistanceCallback> mCallback;
+
+        SingleUseCallback(IGnssAssistanceCallback callback) {
+            mCallback = new AtomicReference<>(callback);
+        }
+
+        @Override
+        public void onError(Throwable e) {
+            try {
+                Objects.requireNonNull(mCallback.getAndSet(null)).onError();
+            } catch (RemoteException r) {
+                throw r.rethrowFromSystemServer();
+            }
+        }
+
+        @Override
+        public void onResult(GnssAssistance result) {
+            try {
+                Objects.requireNonNull(mCallback.getAndSet(null)).onResult(result);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+}
diff --git a/nfc/java/android/nfc/INfcVendorNciCallback.aidl b/location/java/android/location/provider/IGnssAssistanceCallback.aidl
similarity index 72%
rename from nfc/java/android/nfc/INfcVendorNciCallback.aidl
rename to location/java/android/location/provider/IGnssAssistanceCallback.aidl
index 821dc6f..ea38d08 100644
--- a/nfc/java/android/nfc/INfcVendorNciCallback.aidl
+++ b/location/java/android/location/provider/IGnssAssistanceCallback.aidl
@@ -13,12 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.nfc;
+
+package android.location.provider;
+
+import android.location.GnssAssistance;
 
 /**
+ * Binder interface for GNSS assistance callbacks.
  * @hide
  */
-oneway interface INfcVendorNciCallback {
-    void onVendorResponseReceived(int gid, int oid, in byte[] payload);
-    void onVendorNotificationReceived(int gid, int oid, in byte[] payload);
+oneway interface IGnssAssistanceCallback {
+    void onError();
+    void onResult(in GnssAssistance result);
 }
diff --git a/nfc/java/android/nfc/INfcVendorNciCallback.aidl b/location/java/android/location/provider/IGnssAssistanceProvider.aidl
similarity index 63%
copy from nfc/java/android/nfc/INfcVendorNciCallback.aidl
copy to location/java/android/location/provider/IGnssAssistanceProvider.aidl
index 821dc6f..1796e9e 100644
--- a/nfc/java/android/nfc/INfcVendorNciCallback.aidl
+++ b/location/java/android/location/provider/IGnssAssistanceProvider.aidl
@@ -13,12 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.nfc;
+
+package android.location.provider;
+
+import android.location.provider.IGnssAssistanceCallback;
 
 /**
+ * Binder interface for services that implement GNSS assistance providers. Do not implement this
+ * directly, extend {@link GnssAssistanceProviderBase} instead.
  * @hide
  */
-oneway interface INfcVendorNciCallback {
-    void onVendorResponseReceived(int gid, int oid, in byte[] payload);
-    void onVendorNotificationReceived(int gid, int oid, in byte[] payload);
+oneway interface IGnssAssistanceProvider {
+    void request(in IGnssAssistanceCallback callback);
 }
diff --git a/media/java/android/media/FadeManagerConfiguration.java b/media/java/android/media/FadeManagerConfiguration.java
index 6d84e70..b91a5b5 100644
--- a/media/java/android/media/FadeManagerConfiguration.java
+++ b/media/java/android/media/FadeManagerConfiguration.java
@@ -673,6 +673,7 @@
         return config != null ? config.getDuration() : DURATION_NOT_SET;
     }
 
+    @Nullable
     private VolumeShaper.Configuration getVolumeShaperConfigFromWrapper(
             FadeVolumeShaperConfigsWrapper wrapper, boolean isFadeIn) {
         // if no volume shaper config is available, return null
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 09f40e0..f42017d 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -226,6 +226,10 @@
     @GuardedBy("mSessionLock")
     private final ArrayMap<String, MediaStreams> mOngoingMediaStreams = new ArrayMap<>();
 
+    @GuardedBy("mSessionLock")
+    private final ArrayMap<String, RoutingSessionInfo> mPendingSystemSessionReleases =
+            new ArrayMap<>();
+
     public MediaRoute2ProviderService() {
         mHandler = new Handler(Looper.getMainLooper());
     }
@@ -358,7 +362,9 @@
      * @return a {@link MediaStreams} instance that holds the media streams to route as part of the
      *     newly created routing session. May be null if system media capture failed, in which case
      *     you can ignore the return value, as you will receive a call to {@link #onReleaseSession}
-     *     where you can clean up this session
+     *     where you can clean up this session. {@link AudioRecord#startRecording()} must be called
+     *     immediately on {@link MediaStreams#getAudioRecord()} after calling this method, in order
+     *     to start streaming audio to the receiver.
      * @hide
      */
     // TODO: b/362507305 - Unhide once the implementation and CTS are in place.
@@ -417,7 +423,7 @@
         }
 
         AudioFormat audioFormat = formats.mAudioFormat;
-        var mediaStreamsBuilder = new MediaStreams.Builder();
+        var mediaStreamsBuilder = new MediaStreams.Builder(sessionInfo);
         if (audioFormat != null) {
             populateAudioStream(audioFormat, uid, mediaStreamsBuilder);
         }
@@ -458,7 +464,6 @@
         if (uid != Process.INVALID_UID) {
             audioMixingRuleBuilder.addMixRule(AudioMixingRule.RULE_MATCH_UID, uid);
         }
-
         AudioMix mix =
                 new AudioMix.Builder(audioMixingRuleBuilder.build())
                         .setFormat(audioFormat)
@@ -471,7 +476,11 @@
             Log.e(TAG, "Couldn't fetch the audio manager.");
             return;
         }
-        audioManager.registerAudioPolicy(audioPolicy);
+        int audioPolicyResult = audioManager.registerAudioPolicy(audioPolicy);
+        if (audioPolicyResult != AudioManager.SUCCESS) {
+            Log.e(TAG, "Failed to register the audio policy.");
+            return;
+        }
         var audioRecord = audioPolicy.createAudioRecordSink(mix);
         if (audioRecord == null) {
             Log.e(TAG, "Audio record creation failed.");
@@ -521,8 +530,14 @@
         RoutingSessionInfo sessionInfo;
         synchronized (mSessionLock) {
             sessionInfo = mSessionInfos.remove(sessionId);
-            maybeReleaseMediaStreams(sessionId);
-
+            if (Flags.enableMirroringInMediaRouter2()) {
+                if (sessionInfo == null) {
+                    sessionInfo = maybeReleaseMediaStreams(sessionId);
+                }
+                if (sessionInfo == null) {
+                    sessionInfo = mPendingSystemSessionReleases.remove(sessionId);
+                }
+            }
             if (sessionInfo == null) {
                 Log.w(TAG, "notifySessionReleased: Ignoring unknown session info.");
                 return;
@@ -539,18 +554,26 @@
         }
     }
 
-    /** Releases any system media routing resources associated with the given {@code sessionId}. */
-    private void maybeReleaseMediaStreams(String sessionId) {
+    /**
+     * Releases any system media routing resources associated with the given {@code sessionId}.
+     *
+     * @return The {@link RoutingSessionInfo} that corresponds to the released media streams, or
+     *     null if no streams were released.
+     */
+    @Nullable
+    private RoutingSessionInfo maybeReleaseMediaStreams(String sessionId) {
         if (!Flags.enableMirroringInMediaRouter2()) {
-            return;
+            return null;
         }
         synchronized (mSessionLock) {
             var streams = mOngoingMediaStreams.remove(sessionId);
             if (streams != null) {
                 releaseAudioStream(streams.mAudioPolicy, streams.mAudioRecord);
                 // TODO: b/380431086: Release the video stream once implemented.
+                return streams.mSessionInfo;
             }
         }
+        return null;
     }
 
     // We cannot reach the code that requires MODIFY_AUDIO_ROUTING without holding it.
@@ -1019,12 +1042,16 @@
             if (!checkCallerIsSystem()) {
                 return;
             }
-            if (!checkSessionIdIsValid(sessionId, "releaseSession")) {
-                return;
+            synchronized (mSessionLock) {
+                // We proactively release the system media routing session resources when the
+                // system requests it, to ensure it happens immediately.
+                RoutingSessionInfo releasedSession = maybeReleaseMediaStreams(sessionId);
+                if (releasedSession != null) {
+                    mPendingSystemSessionReleases.put(sessionId, releasedSession);
+                } else if (!checkSessionIdIsValid(sessionId, "releaseSession")) {
+                    return;
+                }
             }
-            // We proactively release the system media routing once the system requests it, to
-            // ensure it happens immediately.
-            maybeReleaseMediaStreams(sessionId);
 
             addRequestId(requestId);
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,
@@ -1047,9 +1074,19 @@
         @Nullable private final AudioPolicy mAudioPolicy;
         @Nullable private final AudioRecord mAudioRecord;
 
+        /**
+         * Holds the last {@link RoutingSessionInfo} associated with these streams.
+         *
+         * @hide
+         */
+        @GuardedBy("MediaRoute2ProviderService.this.mSessionLock")
+        @NonNull
+        private RoutingSessionInfo mSessionInfo;
+
         // TODO: b/380431086: Add the video equivalent.
 
         private MediaStreams(Builder builder) {
+            this.mSessionInfo = builder.mSessionInfo;
             this.mAudioPolicy = builder.mAudioPolicy;
             this.mAudioRecord = builder.mAudioRecord;
         }
@@ -1070,9 +1107,19 @@
          */
         public static final class Builder {
 
+            @NonNull private RoutingSessionInfo mSessionInfo;
             @Nullable private AudioPolicy mAudioPolicy;
             @Nullable private AudioRecord mAudioRecord;
 
+            /**
+             * Constructor.
+             *
+             * @param sessionInfo The {@link RoutingSessionInfo} associated with these streams.
+             */
+            Builder(@NonNull RoutingSessionInfo sessionInfo) {
+                mSessionInfo = requireNonNull(sessionInfo);
+            }
+
             /** Populates system media audio-related structures. */
             public Builder setAudioStream(
                     @NonNull AudioPolicy audioPolicy, @NonNull AudioRecord audioRecord) {
diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java
index f7f10df..4f7132a 100644
--- a/media/java/android/media/projection/MediaProjection.java
+++ b/media/java/android/media/projection/MediaProjection.java
@@ -324,6 +324,19 @@
     }
 
     /**
+     * Stops projection.
+     * @hide
+     */
+    public void stop(@StopReason int stopReason) {
+        try {
+            Log.d(TAG, "Content Recording: stopping projection");
+            mImpl.stop(stopReason);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to stop projection", e);
+        }
+    }
+
+    /**
      * Get the underlying IMediaProjection.
      * @hide
      */
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 1fde7d2..3ea2d35 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -29,6 +29,7 @@
 # Input
 per-file input.cpp = file:/INPUT_OWNERS
 
-# PerformanceHint
+# ADPF
 per-file performance_hint.cpp = file:/ADPF_OWNERS
+per-file system_health.cpp = file:/ADPF_OWNERS
 per-file thermal.cpp = file:/ADPF_OWNERS
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 1ccadf9..f629c88 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -396,6 +396,7 @@
     APerformanceHint_notifyWorkloadSpike; # introduced=36
     APerformanceHint_borrowSessionFromJava; # introduced=36
     APerformanceHint_setNativeSurfaces; # introduced=36
+    APerformanceHint_isFeatureSupported; # introduced=36
     AWorkDuration_create; # introduced=VanillaIceCream
     AWorkDuration_release; # introduced=VanillaIceCream
     AWorkDuration_setWorkPeriodStartTimestampNanos; # introduced=VanillaIceCream
@@ -419,7 +420,6 @@
     AThermal_setIThermalServiceForTesting;
     APerformanceHint_setIHintManagerForTesting;
     APerformanceHint_sendHint;
-    APerformanceHint_setUseGraphicsPipelineForTesting;
     APerformanceHint_getThreadIds;
     APerformanceHint_createSessionInternal;
     APerformanceHint_createSessionUsingConfigInternal;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 9257901..7e65523 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -71,26 +71,31 @@
 
 struct APerformanceHintSession;
 
-constexpr int64_t SEND_HINT_TIMEOUT = std::chrono::nanoseconds(100ms).count();
 struct AWorkDuration : public hal::WorkDuration {};
 struct ASessionCreationConfig : public SessionCreationConfig {
     std::vector<wp<IBinder>> layers{};
-    bool hasMode(hal::SessionMode&& mode) {
+    bool hasMode(hal::SessionMode mode) {
         return std::find(modesToEnable.begin(), modesToEnable.end(), mode) != modesToEnable.end();
     }
+    void setMode(hal::SessionMode mode, bool enabled) {
+        if (hasMode(mode)) {
+            if (!enabled) {
+                std::erase(modesToEnable, mode);
+            }
+        } else if (enabled) {
+            modesToEnable.push_back(mode);
+        }
+    }
 };
 
-bool kForceGraphicsPipeline = false;
-
-bool useGraphicsPipeline() {
-    return android::os::adpf_graphics_pipeline() || kForceGraphicsPipeline;
-}
-
 // A pair of values that determine the behavior of the
 // load hint rate limiter, to only allow "X hints every Y seconds"
-constexpr double kLoadHintInterval = std::chrono::nanoseconds(2s).count();
+constexpr int64_t kLoadHintInterval = std::chrono::nanoseconds(2s).count();
 constexpr double kMaxLoadHintsPerInterval = 20;
-constexpr double kReplenishRate = kMaxLoadHintsPerInterval / kLoadHintInterval;
+// Replenish rate is used for new rate limiting behavior, it currently replenishes at a rate of
+// 20 / 2s = 1 per 100us, which is the same limit as before, just enforced differently
+constexpr double kReplenishRate = kMaxLoadHintsPerInterval / static_cast<double>(kLoadHintInterval);
+constexpr int64_t kSendHintTimeout = kLoadHintInterval / kMaxLoadHintsPerInterval;
 bool kForceNewHintBehavior = false;
 
 template <class T>
@@ -149,9 +154,7 @@
     std::future<bool> mChannelCreationFinished;
 };
 
-class SupportInfoWrapper {
-public:
-    SupportInfoWrapper(hal::SupportInfo& info);
+struct SupportInfoWrapper : public hal::SupportInfo {
     bool isSessionModeSupported(hal::SessionMode mode);
     bool isSessionHintSupported(hal::SessionHint hint);
 
@@ -162,7 +165,6 @@
         // over that much and cutting off any extra values
         return (supportBitfield >> static_cast<int>(enumValue)) % 2;
     }
-    hal::SupportInfo mSupportInfo;
 };
 
 class HintManagerClient : public IHintManager::BnHintManagerClient {
@@ -188,9 +190,9 @@
                                            bool isJava = false);
     APerformanceHintSession* getSessionFromJava(JNIEnv* _Nonnull env, jobject _Nonnull sessionObj);
 
-    APerformanceHintSession* createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig,
-                                                      hal::SessionTag tag = hal::SessionTag::APP,
-                                                      bool isJava = false);
+    int createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig,
+                                 APerformanceHintSession** sessionPtr,
+                                 hal::SessionTag tag = hal::SessionTag::APP, bool isJava = false);
     int64_t getPreferredRateNanos() const;
     int32_t getMaxGraphicsPipelineThreadsCount();
     FMQWrapper& getFMQWrapper();
@@ -202,6 +204,7 @@
                                          std::vector<T>& out);
     ndk::SpAIBinder& getToken();
     SupportInfoWrapper& getSupportInfo();
+    bool isFeatureSupported(APerformanceHintFeature feature);
 
 private:
     static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager);
@@ -239,8 +242,8 @@
     int setPreferPowerEfficiency(bool enabled);
     int reportActualWorkDuration(AWorkDuration* workDuration);
     bool isJava();
-    status_t setNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls,
-                               int numSurfaceControls);
+    status_t setNativeSurfaces(ANativeWindow** windows, size_t numWindows,
+                               ASurfaceControl** controls, size_t numSurfaceControls);
 
 private:
     friend struct APerformanceHintManager;
@@ -294,14 +297,12 @@
 
 // ===================================== SupportInfoWrapper implementation
 
-SupportInfoWrapper::SupportInfoWrapper(hal::SupportInfo& info) : mSupportInfo(info) {}
-
 bool SupportInfoWrapper::isSessionHintSupported(hal::SessionHint hint) {
-    return getEnumSupportFromBitfield(hint, mSupportInfo.sessionHints);
+    return getEnumSupportFromBitfield(hint, sessionHints);
 }
 
 bool SupportInfoWrapper::isSessionModeSupported(hal::SessionMode mode) {
-    return getEnumSupportFromBitfield(mode, mSupportInfo.sessionModes);
+    return getEnumSupportFromBitfield(mode, sessionModes);
 }
 
 // ===================================== APerformanceHintManager implementation
@@ -386,12 +387,14 @@
             .targetWorkDurationNanos = initialTargetWorkDurationNanos,
     }};
 
-    return APerformanceHintManager::createSessionUsingConfig(&creationConfig, tag, isJava);
+    APerformanceHintSession* sessionOut;
+    APerformanceHintManager::createSessionUsingConfig(&creationConfig, &sessionOut, tag, isJava);
+    return sessionOut;
 }
 
-APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig(
-        ASessionCreationConfig* sessionCreationConfig, hal::SessionTag tag, bool isJava) {
-    std::shared_ptr<IHintSession> session;
+int APerformanceHintManager::createSessionUsingConfig(ASessionCreationConfig* sessionCreationConfig,
+                                                      APerformanceHintSession** sessionOut,
+                                                      hal::SessionTag tag, bool isJava) {
     hal::SessionConfig sessionConfig{.id = -1};
     ndk::ScopedAStatus ret;
 
@@ -411,31 +414,65 @@
         }
     }
 
+    bool autoCpu = sessionCreationConfig->hasMode(hal::SessionMode::AUTO_CPU);
+    bool autoGpu = sessionCreationConfig->hasMode(hal::SessionMode::AUTO_GPU);
+
+    if (autoCpu || autoGpu) {
+        LOG_ALWAYS_FATAL_IF(!sessionCreationConfig->hasMode(hal::SessionMode::GRAPHICS_PIPELINE),
+                            "Automatic session timing enabled without graphics pipeline mode");
+    }
+
+    if (autoCpu && !mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_CPU)) {
+        ALOGE("Automatic CPU timing enabled but not supported");
+        return ENOTSUP;
+    }
+
+    if (autoGpu && !mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_GPU)) {
+        ALOGE("Automatic GPU timing enabled but not supported");
+        return ENOTSUP;
+    }
+
+    IHintManager::SessionCreationReturn returnValue;
     ret = mHintManager->createHintSessionWithConfig(mToken, tag,
                                                     *static_cast<SessionCreationConfig*>(
                                                             sessionCreationConfig),
-                                                    &sessionConfig, &session);
+                                                    &sessionConfig, &returnValue);
 
     sessionCreationConfig->layerTokens.clear();
 
-    if (!ret.isOk() || !session) {
+    if (!ret.isOk() || !returnValue.session) {
         ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage());
-        return nullptr;
+        switch (ret.getExceptionCode()) {
+            case binder::Status::EX_UNSUPPORTED_OPERATION:
+                return ENOTSUP;
+            case binder::Status::EX_ILLEGAL_ARGUMENT:
+                return EINVAL;
+            default:
+                return EPIPE;
+        }
     }
 
-    auto out = new APerformanceHintSession(mHintManager, std::move(session),
+    auto out = new APerformanceHintSession(mHintManager, std::move(returnValue.session),
                                            mClientData.preferredRateNanos,
                                            sessionCreationConfig->targetWorkDurationNanos, isJava,
                                            sessionConfig.id == -1
                                                    ? std::nullopt
                                                    : std::make_optional<hal::SessionConfig>(
                                                              std::move(sessionConfig)));
+
+    *sessionOut = out;
+
     std::scoped_lock lock(sHintMutex);
     out->traceThreads(sessionCreationConfig->tids);
     out->traceTargetDuration(sessionCreationConfig->targetWorkDurationNanos);
     out->traceModes(sessionCreationConfig->modesToEnable);
 
-    return out;
+    if (returnValue.pipelineThreadLimitExceeded) {
+        ALOGE("Graphics pipeline session thread limit exceeded!");
+        return EBUSY;
+    }
+
+    return 0;
 }
 
 APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env,
@@ -480,6 +517,25 @@
     return mSupportInfoWrapper;
 }
 
+bool APerformanceHintManager::isFeatureSupported(APerformanceHintFeature feature) {
+    switch (feature) {
+        case (APERF_HINT_SESSIONS):
+            return mSupportInfoWrapper.usesSessions;
+        case (APERF_HINT_POWER_EFFICIENCY):
+            return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::POWER_EFFICIENCY);
+        case (APERF_HINT_SURFACE_BINDING):
+            return mSupportInfoWrapper.compositionData.isSupported;
+        case (APERF_HINT_GRAPHICS_PIPELINE):
+            return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::GRAPHICS_PIPELINE);
+        case (APERF_HINT_AUTO_CPU):
+            return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_CPU);
+        case (APERF_HINT_AUTO_GPU):
+            return mSupportInfoWrapper.isSessionModeSupported(hal::SessionMode::AUTO_GPU);
+        default:
+            return false;
+    }
+}
+
 // ===================================== APerformanceHintSession implementation
 
 constexpr int kNumEnums = enum_size<hal::SessionHint>();
@@ -512,10 +568,6 @@
 }
 
 int APerformanceHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
-    if (targetDurationNanos <= 0) {
-        ALOGE("%s: targetDurationNanos must be positive", __FUNCTION__);
-        return EINVAL;
-    }
     std::scoped_lock lock(sHintMutex);
     if (mTargetDurationNanos == targetDurationNanos) {
         return 0;
@@ -546,7 +598,6 @@
                                    .workPeriodStartTimestampNanos = 0,
                                    .cpuDurationNanos = actualDurationNanos,
                                    .gpuDurationNanos = 0};
-
     return reportActualWorkDurationInternal(static_cast<AWorkDuration*>(&workDuration));
 }
 
@@ -556,17 +607,24 @@
 
 int APerformanceHintSession::sendHints(std::vector<hal::SessionHint>& hints, int64_t now,
                                        const char*) {
-    std::scoped_lock lock(sHintMutex);
+    auto& supportInfo = APerformanceHintManager::getInstance()->getSupportInfo();
+
+    // Drop all unsupported hints, there's not much point reporting errors or warnings for this
+    std::erase_if(hints,
+                  [&](hal::SessionHint hint) { return !supportInfo.isSessionHintSupported(hint); });
+
     if (hints.empty()) {
-        return EINVAL;
-    }
-    for (auto&& hint : hints) {
-        if (static_cast<int32_t>(hint) < 0 || static_cast<int32_t>(hint) >= kNumEnums) {
-            ALOGE("%s: invalid session hint %d", __FUNCTION__, hint);
-            return EINVAL;
-        }
+        // We successfully sent all hints we were able to, technically
+        return 0;
     }
 
+    for (auto&& hint : hints) {
+        LOG_ALWAYS_FATAL_IF(static_cast<int32_t>(hint) < 0 ||
+                                    static_cast<int32_t>(hint) >= kNumEnums,
+                            "%s: invalid session hint %d", __FUNCTION__, hint);
+    }
+
+    std::scoped_lock lock(sHintMutex);
     if (useNewLoadHintBehavior()) {
         if (!APerformanceHintManager::getInstance()->canSendLoadHints(hints, now)) {
             return EBUSY;
@@ -575,7 +633,7 @@
     // keep old rate limiter behavior for legacy flag
     else {
         for (auto&& hint : hints) {
-            if (now < (mLastHintSentTimestamp[static_cast<int32_t>(hint)] + SEND_HINT_TIMEOUT)) {
+            if (now < (mLastHintSentTimestamp[static_cast<int32_t>(hint)] + kSendHintTimeout)) {
                 return EBUSY;
             }
         }
@@ -651,7 +709,9 @@
     }
     std::vector<int32_t> tids(threadIds, threadIds + size);
     ndk::ScopedAStatus ret = mHintManager->setHintSessionThreads(mHintSession, tids);
-    if (!ret.isOk()) {
+
+    // Illegal state means there were too many graphics pipeline threads
+    if (!ret.isOk() && ret.getExceptionCode() != EX_SERVICE_SPECIFIC) {
         ALOGE("%s: failed: %s", __FUNCTION__, ret.getMessage());
         if (ret.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
             return EINVAL;
@@ -663,8 +723,10 @@
 
     std::scoped_lock lock(sHintMutex);
     traceThreads(tids);
+    bool tooManyThreads =
+            ret.getExceptionCode() == EX_SERVICE_SPECIFIC && ret.getServiceSpecificError() == 5;
 
-    return 0;
+    return tooManyThreads ? EBUSY : 0;
 }
 
 int APerformanceHintSession::getThreadIds(int32_t* const threadIds, size_t* size) {
@@ -711,10 +773,16 @@
 
 int APerformanceHintSession::reportActualWorkDurationInternal(AWorkDuration* workDuration) {
     int64_t actualTotalDurationNanos = workDuration->durationNanos;
-    traceActualDuration(workDuration->durationNanos);
     int64_t now = uptimeNanos();
     workDuration->timeStampNanos = now;
     std::scoped_lock lock(sHintMutex);
+
+    if (mTargetDurationNanos <= 0) {
+        ALOGE("Cannot report work durations if the target duration is not positive.");
+        return EINVAL;
+    }
+
+    traceActualDuration(actualTotalDurationNanos);
     mActualWorkDurations.push_back(std::move(*workDuration));
 
     if (actualTotalDurationNanos >= mTargetDurationNanos) {
@@ -757,9 +825,9 @@
     return 0;
 }
 
-status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, int numWindows,
+status_t APerformanceHintSession::setNativeSurfaces(ANativeWindow** windows, size_t numWindows,
                                                     ASurfaceControl** controls,
-                                                    int numSurfaceControls) {
+                                                    size_t numSurfaceControls) {
     if (!mSessionConfig.has_value()) {
         return ENOTSUP;
     }
@@ -774,7 +842,10 @@
         ndkLayerHandles.emplace_back(ndk::SpAIBinder(AIBinder_fromPlatformBinder(handle)));
     }
 
-    mHintSession->associateToLayers(ndkLayerHandles);
+    auto ret = mHintSession->associateToLayers(ndkLayerHandles);
+    if (!ret.isOk()) {
+        return EPIPE;
+    }
     return 0;
 }
 
@@ -857,6 +928,11 @@
             }
             return true;
         });
+
+        // If we're unit testing the FMQ, we should block for it to finish completing
+        if (gForceFMQEnabled.has_value()) {
+            mChannelCreationFinished.wait();
+        }
     }
     return isActive();
 }
@@ -1029,7 +1105,8 @@
     ATrace_setCounter((mSessionName + " target duration").c_str(), targetDuration);
 }
 
-// ===================================== C API
+// ===================================== Start of C API
+
 APerformanceHintManager* APerformanceHint_getManager() {
     return APerformanceHintManager::getInstance();
 }
@@ -1037,10 +1114,16 @@
 #define VALIDATE_PTR(ptr) \
     LOG_ALWAYS_FATAL_IF(ptr == nullptr, "%s: " #ptr " is nullptr", __FUNCTION__);
 
+#define HARD_VALIDATE_INT(value, cmp)                                        \
+    LOG_ALWAYS_FATAL_IF(!(value cmp),                                        \
+                        "%s: Invalid value. Check failed: (" #value " " #cmp \
+                        ") with value: %" PRIi64,                            \
+                        __FUNCTION__, static_cast<int64_t>(value));
+
 #define VALIDATE_INT(value, cmp)                                                             \
     if (!(value cmp)) {                                                                      \
         ALOGE("%s: Invalid value. Check failed: (" #value " " #cmp ") with value: %" PRIi64, \
-              __FUNCTION__, value);                                                          \
+              __FUNCTION__, static_cast<int64_t>(value));                                    \
         return EINVAL;                                                                       \
     }
 
@@ -1058,19 +1141,27 @@
     return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
 }
 
-APerformanceHintSession* APerformanceHint_createSessionUsingConfig(
-        APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig) {
+int APerformanceHint_createSessionUsingConfig(APerformanceHintManager* manager,
+                                              ASessionCreationConfig* sessionCreationConfig,
+                                              APerformanceHintSession** sessionOut) {
     VALIDATE_PTR(manager);
     VALIDATE_PTR(sessionCreationConfig);
-    return manager->createSessionUsingConfig(sessionCreationConfig);
+    VALIDATE_PTR(sessionOut);
+    *sessionOut = nullptr;
+
+    return manager->createSessionUsingConfig(sessionCreationConfig, sessionOut);
 }
 
-APerformanceHintSession* APerformanceHint_createSessionUsingConfigInternal(
-        APerformanceHintManager* manager, ASessionCreationConfig* sessionCreationConfig,
-        SessionTag tag) {
+int APerformanceHint_createSessionUsingConfigInternal(APerformanceHintManager* manager,
+                                                      ASessionCreationConfig* sessionCreationConfig,
+                                                      APerformanceHintSession** sessionOut,
+                                                      SessionTag tag) {
     VALIDATE_PTR(manager);
     VALIDATE_PTR(sessionCreationConfig);
-    return manager->createSessionUsingConfig(sessionCreationConfig,
+    VALIDATE_PTR(sessionOut);
+    *sessionOut = nullptr;
+
+    return manager->createSessionUsingConfig(sessionCreationConfig, sessionOut,
                                              static_cast<hal::SessionTag>(tag));
 }
 
@@ -1111,6 +1202,7 @@
 int APerformanceHint_updateTargetWorkDuration(APerformanceHintSession* session,
                                               int64_t targetDurationNanos) {
     VALIDATE_PTR(session)
+    VALIDATE_INT(targetDurationNanos, >= 0)
     return session->updateTargetWorkDuration(targetDurationNanos);
 }
 
@@ -1204,13 +1296,23 @@
 }
 
 int APerformanceHint_setNativeSurfaces(APerformanceHintSession* session,
-                                       ANativeWindow** nativeWindows, int nativeWindowsSize,
-                                       ASurfaceControl** surfaceControls, int surfaceControlsSize) {
+                                       ANativeWindow** nativeWindows, size_t nativeWindowsSize,
+                                       ASurfaceControl** surfaceControls,
+                                       size_t surfaceControlsSize) {
     VALIDATE_PTR(session)
     return session->setNativeSurfaces(nativeWindows, nativeWindowsSize, surfaceControls,
                                       surfaceControlsSize);
 }
 
+bool APerformanceHint_isFeatureSupported(APerformanceHintFeature feature) {
+    APerformanceHintManager* manager = APerformanceHintManager::getInstance();
+    if (manager == nullptr) {
+        // Clearly whatever it is isn't supported in this case
+        return false;
+    }
+    return manager->isFeatureSupported(feature);
+}
+
 AWorkDuration* AWorkDuration_create() {
     return new AWorkDuration();
 }
@@ -1265,78 +1367,32 @@
 
 void ASessionCreationConfig_release(ASessionCreationConfig* config) {
     VALIDATE_PTR(config)
-
     delete config;
 }
 
-int ASessionCreationConfig_setTids(ASessionCreationConfig* config, const pid_t* tids, size_t size) {
+void ASessionCreationConfig_setTids(ASessionCreationConfig* config, const pid_t* tids,
+                                    size_t size) {
     VALIDATE_PTR(config)
     VALIDATE_PTR(tids)
+    HARD_VALIDATE_INT(size, > 0)
 
-    if (!useGraphicsPipeline()) {
-        return ENOTSUP;
-    }
-
-    if (size <= 0) {
-        LOG_ALWAYS_FATAL_IF(size <= 0,
-                            "%s: Invalid value. Thread id list size should be greater than zero.",
-                            __FUNCTION__);
-        return EINVAL;
-    }
     config->tids = std::vector<int32_t>(tids, tids + size);
-    return 0;
 }
 
-int ASessionCreationConfig_setTargetWorkDurationNanos(ASessionCreationConfig* config,
-                                                      int64_t targetWorkDurationNanos) {
+void ASessionCreationConfig_setTargetWorkDurationNanos(ASessionCreationConfig* config,
+                                                       int64_t targetWorkDurationNanos) {
     VALIDATE_PTR(config)
-    VALIDATE_INT(targetWorkDurationNanos, >= 0)
-
-    if (!useGraphicsPipeline()) {
-        return ENOTSUP;
-    }
-
     config->targetWorkDurationNanos = targetWorkDurationNanos;
-    return 0;
 }
 
-int ASessionCreationConfig_setPreferPowerEfficiency(ASessionCreationConfig* config, bool enabled) {
+void ASessionCreationConfig_setPreferPowerEfficiency(ASessionCreationConfig* config, bool enabled) {
     VALIDATE_PTR(config)
-
-    if (!useGraphicsPipeline()) {
-        return ENOTSUP;
-    }
-
-    if (enabled) {
-        config->modesToEnable.push_back(hal::SessionMode::POWER_EFFICIENCY);
-    } else {
-        std::erase(config->modesToEnable, hal::SessionMode::POWER_EFFICIENCY);
-    }
-    return 0;
+    config->setMode(hal::SessionMode::POWER_EFFICIENCY, enabled);
 }
 
-int ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, bool enabled) {
+void ASessionCreationConfig_setGraphicsPipeline(ASessionCreationConfig* config, bool enabled) {
     VALIDATE_PTR(config)
-
-    if (!useGraphicsPipeline()) {
-        return ENOTSUP;
-    }
-
-    if (enabled) {
-        config->modesToEnable.push_back(hal::SessionMode::GRAPHICS_PIPELINE);
-    } else {
-        std::erase(config->modesToEnable, hal::SessionMode::GRAPHICS_PIPELINE);
-
-        // Remove automatic timing modes if we turn off GRAPHICS_PIPELINE,
-        // as it is a strict pre-requisite for these to run
-        std::erase(config->modesToEnable, hal::SessionMode::AUTO_CPU);
-        std::erase(config->modesToEnable, hal::SessionMode::AUTO_GPU);
-    }
-    return 0;
-}
-
-void APerformanceHint_setUseGraphicsPipelineForTesting(bool enabled) {
-    kForceGraphicsPipeline = enabled;
+    config->setMode(hal::SessionMode::GRAPHICS_PIPELINE, enabled);
 }
 
 void APerformanceHint_getRateLimiterPropertiesForTesting(int32_t* maxLoadHintsPerInterval,
@@ -1349,47 +1405,21 @@
     kForceNewHintBehavior = newBehavior;
 }
 
-int ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config,
-                                             ANativeWindow** nativeWindows, int nativeWindowsSize,
-                                             ASurfaceControl** surfaceControls,
-                                             int surfaceControlsSize) {
+void ASessionCreationConfig_setNativeSurfaces(ASessionCreationConfig* config,
+                                              ANativeWindow** nativeWindows,
+                                              size_t nativeWindowsSize,
+                                              ASurfaceControl** surfaceControls,
+                                              size_t surfaceControlsSize) {
     VALIDATE_PTR(config)
-
     APerformanceHintManager::layersFromNativeSurfaces<wp<IBinder>>(nativeWindows, nativeWindowsSize,
                                                                    surfaceControls,
                                                                    surfaceControlsSize,
                                                                    config->layers);
-
-    if (config->layers.empty()) {
-        return EINVAL;
-    }
-
-    return 0;
 }
 
-int ASessionCreationConfig_setUseAutoTiming(ASessionCreationConfig* _Nonnull config, bool cpu,
-                                            bool gpu) {
+void ASessionCreationConfig_setUseAutoTiming(ASessionCreationConfig* _Nonnull config, bool cpu,
+                                             bool gpu) {
     VALIDATE_PTR(config)
-    if ((cpu || gpu) && !config->hasMode(hal::SessionMode::GRAPHICS_PIPELINE)) {
-        ALOGE("Automatic timing is not supported unless graphics pipeline mode is enabled first");
-        return ENOTSUP;
-    }
-
-    if (config->hasMode(hal::SessionMode::AUTO_CPU)) {
-        if (!cpu) {
-            std::erase(config->modesToEnable, hal::SessionMode::AUTO_CPU);
-        }
-    } else if (cpu) {
-        config->modesToEnable.push_back(static_cast<hal::SessionMode>(hal::SessionMode::AUTO_CPU));
-    }
-
-    if (config->hasMode(hal::SessionMode::AUTO_GPU)) {
-        if (!gpu) {
-            std::erase(config->modesToEnable, hal::SessionMode::AUTO_GPU);
-        }
-    } else if (gpu) {
-        config->modesToEnable.push_back(static_cast<hal::SessionMode>(hal::SessionMode::AUTO_GPU));
-    }
-
-    return 0;
+    config->setMode(hal::SessionMode::AUTO_CPU, cpu);
+    config->setMode(hal::SessionMode::AUTO_GPU, gpu);
 }
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index e3c10f6..f68fa1a 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -49,12 +49,87 @@
 using namespace android;
 using namespace testing;
 
+constexpr int64_t DEFAULT_TARGET_NS = 16666666L;
+
+template <class T, void (*D)(T*)>
+std::shared_ptr<T> wrapSP(T* incoming) {
+    return incoming == nullptr ? nullptr : std::shared_ptr<T>(incoming, [](T* ptr) { D(ptr); });
+}
+constexpr auto&& wrapSession = wrapSP<APerformanceHintSession, APerformanceHint_closeSession>;
+constexpr auto&& wrapConfig = wrapSP<ASessionCreationConfig, ASessionCreationConfig_release>;
+constexpr auto&& wrapWorkDuration = wrapSP<AWorkDuration, AWorkDuration_release>;
+
+std::shared_ptr<ASessionCreationConfig> createConfig() {
+    return wrapConfig(ASessionCreationConfig_create());
+}
+
+struct ConfigCreator {
+    std::vector<int32_t> tids{1, 2};
+    int64_t targetDuration = DEFAULT_TARGET_NS;
+    bool powerEfficient = false;
+    bool graphicsPipeline = false;
+    std::vector<ANativeWindow*> nativeWindows{};
+    std::vector<ASurfaceControl*> surfaceControls{};
+    bool autoCpu = false;
+    bool autoGpu = false;
+};
+
+struct SupportHelper {
+    bool hintSessions : 1;
+    bool powerEfficiency : 1;
+    bool bindToSurface : 1;
+    bool graphicsPipeline : 1;
+    bool autoCpu : 1;
+    bool autoGpu : 1;
+};
+
+SupportHelper getSupportHelper() {
+    return {
+            .hintSessions = APerformanceHint_isFeatureSupported(APERF_HINT_SESSIONS),
+            .powerEfficiency = APerformanceHint_isFeatureSupported(APERF_HINT_POWER_EFFICIENCY),
+            .bindToSurface = APerformanceHint_isFeatureSupported(APERF_HINT_SURFACE_BINDING),
+            .graphicsPipeline = APerformanceHint_isFeatureSupported(APERF_HINT_GRAPHICS_PIPELINE),
+            .autoCpu = APerformanceHint_isFeatureSupported(APERF_HINT_AUTO_CPU),
+            .autoGpu = APerformanceHint_isFeatureSupported(APERF_HINT_AUTO_GPU),
+    };
+}
+
+SupportHelper getFullySupportedSupportHelper() {
+    return {
+            .hintSessions = true,
+            .powerEfficiency = true,
+            .graphicsPipeline = true,
+            .autoCpu = true,
+            .autoGpu = true,
+    };
+}
+
+std::shared_ptr<ASessionCreationConfig> configFromCreator(ConfigCreator&& creator) {
+    auto config = createConfig();
+
+    ASessionCreationConfig_setTids(config.get(), creator.tids.data(), creator.tids.size());
+    ASessionCreationConfig_setTargetWorkDurationNanos(config.get(), creator.targetDuration);
+    ASessionCreationConfig_setPreferPowerEfficiency(config.get(), creator.powerEfficient);
+    ASessionCreationConfig_setGraphicsPipeline(config.get(), creator.graphicsPipeline);
+    ASessionCreationConfig_setNativeSurfaces(config.get(),
+                                             creator.nativeWindows.size() > 0
+                                                     ? creator.nativeWindows.data()
+                                                     : nullptr,
+                                             creator.nativeWindows.size(),
+                                             creator.surfaceControls.size() > 0
+                                                     ? creator.surfaceControls.data()
+                                                     : nullptr,
+                                             creator.surfaceControls.size());
+    ASessionCreationConfig_setUseAutoTiming(config.get(), creator.autoCpu, creator.autoGpu);
+    return config;
+}
+
 class MockIHintManager : public IHintManager {
 public:
     MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
                 (const SpAIBinder& token, hal::SessionTag tag,
                  const SessionCreationConfig& creationConfig, hal::SessionConfig* config,
-                 std::shared_ptr<IHintSession>* _aidl_return),
+                 IHintManager::SessionCreationReturn* _aidl_return),
                 (override));
     MOCK_METHOD(ScopedAStatus, setHintSessionThreads,
                 (const std::shared_ptr<IHintSession>& hintSession,
@@ -115,8 +190,9 @@
         APerformanceHint_getRateLimiterPropertiesForTesting(&mMaxLoadHintsPerInterval,
                                                             &mLoadHintInterval);
         APerformanceHint_setIHintManagerForTesting(&mMockIHintManager);
-        APerformanceHint_setUseGraphicsPipelineForTesting(true);
         APerformanceHint_setUseNewLoadHintBehaviorForTesting(true);
+        mTids.push_back(1);
+        mTids.push_back(2);
     }
 
     void TearDown() override {
@@ -130,20 +206,22 @@
         ON_CALL(*mMockIHintManager, registerClient(_, _))
                 .WillByDefault(
                         DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); }));
+        ON_CALL(*mMockIHintManager, isRemote()).WillByDefault(Return(true));
         return APerformanceHint_getManager();
     }
 
-    APerformanceHintSession* createSession(APerformanceHintManager* manager,
-                                           int64_t targetDuration = 56789L, bool isHwui = false) {
+    void prepareSessionMock() {
         mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
         const int64_t sessionId = 123;
-        std::vector<int32_t> tids;
-        tids.push_back(1);
-        tids.push_back(2);
+
+        mSessionCreationReturn = IHintManager::SessionCreationReturn{
+                .session = mMockSession,
+                .pipelineThreadLimitExceeded = false,
+        };
 
         ON_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _))
                 .WillByDefault(DoAll(SetArgPointee<3>(hal::SessionConfig({.id = sessionId})),
-                                     SetArgPointee<4>(std::shared_ptr<IHintSession>(mMockSession)),
+                                     SetArgPointee<4>(mSessionCreationReturn),
                                      [] { return ScopedAStatus::ok(); }));
 
         ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
@@ -161,48 +239,36 @@
         ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
             return ScopedAStatus::ok();
         });
-        if (isHwui) {
-            return APerformanceHint_createSessionInternal(manager, tids.data(), tids.size(),
-                                                          targetDuration, SessionTag::HWUI);
-        }
-        return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
     }
 
-    APerformanceHintSession* createSessionUsingConfig(APerformanceHintManager* manager,
-                                                      SessionCreationConfig config,
-                                                      bool isHwui = false) {
-        mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
-        const int64_t sessionId = 123;
-
-        ON_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _))
-                .WillByDefault(DoAll(SetArgPointee<3>(hal::SessionConfig({.id = sessionId})),
-                                     SetArgPointee<4>(std::shared_ptr<IHintSession>(mMockSession)),
-                                     [] { return ScopedAStatus::ok(); }));
-
-        ON_CALL(*mMockIHintManager, setHintSessionThreads(_, _)).WillByDefault([] {
-            return ScopedAStatus::ok();
-        });
-        ON_CALL(*mMockSession, sendHint(_)).WillByDefault([] { return ScopedAStatus::ok(); });
-        ON_CALL(*mMockSession, setMode(_, true)).WillByDefault([] { return ScopedAStatus::ok(); });
-        ON_CALL(*mMockSession, close()).WillByDefault([] { return ScopedAStatus::ok(); });
-        ON_CALL(*mMockSession, updateTargetWorkDuration(_)).WillByDefault([] {
-            return ScopedAStatus::ok();
-        });
-        ON_CALL(*mMockSession, reportActualWorkDuration(_, _)).WillByDefault([] {
-            return ScopedAStatus::ok();
-        });
-        ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
-            return ScopedAStatus::ok();
-        });
-
+    std::shared_ptr<APerformanceHintSession> createSession(APerformanceHintManager* manager,
+                                                           int64_t targetDuration = 56789L,
+                                                           bool isHwui = false) {
+        prepareSessionMock();
         if (isHwui) {
-            return APerformanceHint_createSessionUsingConfigInternal(
-                    manager, reinterpret_cast<ASessionCreationConfig*>(&config), SessionTag::HWUI);
+            return wrapSession(APerformanceHint_createSessionInternal(manager, mTids.data(),
+                                                                      mTids.size(), targetDuration,
+                                                                      SessionTag::HWUI));
+        }
+        return wrapSession(APerformanceHint_createSession(manager, mTids.data(), mTids.size(),
+                                                          targetDuration));
+    }
+
+    std::shared_ptr<APerformanceHintSession> createSessionUsingConfig(
+            APerformanceHintManager* manager, std::shared_ptr<ASessionCreationConfig>& config,
+            bool isHwui = false) {
+        prepareSessionMock();
+        APerformanceHintSession* session;
+        int out = 0;
+        if (isHwui) {
+            out = APerformanceHint_createSessionUsingConfigInternal(manager, config.get(), &session,
+                                                                    SessionTag::HWUI);
         }
 
-        return APerformanceHint_createSessionUsingConfig(manager,
-                                                         reinterpret_cast<ASessionCreationConfig*>(
-                                                                 &config));
+        out = APerformanceHint_createSessionUsingConfig(manager, config.get(), &session);
+        EXPECT_EQ(out, 0);
+
+        return wrapSession(session);
     }
 
     void setFMQEnabled(bool enabled) {
@@ -233,11 +299,13 @@
     uint32_t mWriteBits = 0x00000002;
     std::shared_ptr<NiceMock<MockIHintManager>> mMockIHintManager = nullptr;
     std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
+    IHintManager::SessionCreationReturn mSessionCreationReturn;
     std::shared_ptr<AidlMessageQueue<hal::ChannelMessage, SynchronizedReadWrite>> mMockFMQ;
     std::shared_ptr<AidlMessageQueue<int8_t, SynchronizedReadWrite>> mMockFlagQueue;
     hardware::EventFlag* mEventFlag;
     int kMockQueueSize = 20;
     bool mUsingFMQ = false;
+    std::vector<int> mTids;
 
     IHintManager::HintManagerClientData mClientData{
             .powerHalVersion = 6,
@@ -273,107 +341,109 @@
 
 TEST_F(PerformanceHintTest, TestSession) {
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
 
     int64_t targetDurationNanos = 10;
     EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
-    int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+    int result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos);
     EXPECT_EQ(0, result);
 
     // subsequent call with same target should be ignored but return no error
-    result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+    result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos);
     EXPECT_EQ(0, result);
 
+    Mock::VerifyAndClearExpectations(mMockSession.get());
+
     usleep(2); // Sleep for longer than preferredUpdateRateNanos.
     int64_t actualDurationNanos = 20;
     std::vector<int64_t> actualDurations;
     actualDurations.push_back(20);
     EXPECT_CALL(*mMockSession, reportActualWorkDuration2(_)).Times(Exactly(1));
-    result = APerformanceHint_reportActualWorkDuration(session, actualDurationNanos);
+    EXPECT_CALL(*mMockSession, updateTargetWorkDuration(_)).Times(Exactly(1));
+    result = APerformanceHint_reportActualWorkDuration(session.get(), actualDurationNanos);
     EXPECT_EQ(0, result);
-    result = APerformanceHint_updateTargetWorkDuration(session, -1L);
+    result = APerformanceHint_reportActualWorkDuration(session.get(), -1L);
     EXPECT_EQ(EINVAL, result);
-    result = APerformanceHint_reportActualWorkDuration(session, -1L);
+    result = APerformanceHint_updateTargetWorkDuration(session.get(), 0);
+    EXPECT_EQ(0, result);
+    result = APerformanceHint_updateTargetWorkDuration(session.get(), -2);
+    EXPECT_EQ(EINVAL, result);
+    result = APerformanceHint_reportActualWorkDuration(session.get(), 12L);
     EXPECT_EQ(EINVAL, result);
 
     SessionHint hintId = SessionHint::CPU_LOAD_RESET;
     EXPECT_CALL(*mMockSession, sendHint(Eq(hintId))).Times(Exactly(1));
-    result = APerformanceHint_sendHint(session, hintId);
+    result = APerformanceHint_sendHint(session.get(), hintId);
     EXPECT_EQ(0, result);
     EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_UP))).Times(Exactly(1));
-    result = APerformanceHint_notifyWorkloadIncrease(session, true, false, "Test hint");
+    result = APerformanceHint_notifyWorkloadIncrease(session.get(), true, false, "Test hint");
     EXPECT_EQ(0, result);
     EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_RESET))).Times(Exactly(1));
     EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::GPU_LOAD_RESET))).Times(Exactly(1));
-    result = APerformanceHint_notifyWorkloadReset(session, true, true, "Test hint");
+    result = APerformanceHint_notifyWorkloadReset(session.get(), true, true, "Test hint");
     EXPECT_EQ(0, result);
     EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::CPU_LOAD_SPIKE))).Times(Exactly(1));
     EXPECT_CALL(*mMockSession, sendHint(Eq(SessionHint::GPU_LOAD_SPIKE))).Times(Exactly(1));
-    result = APerformanceHint_notifyWorkloadSpike(session, true, true, "Test hint");
+    result = APerformanceHint_notifyWorkloadSpike(session.get(), true, true, "Test hint");
     EXPECT_EQ(0, result);
 
-    result = APerformanceHint_sendHint(session, static_cast<SessionHint>(-1));
-    EXPECT_EQ(EINVAL, result);
+    EXPECT_DEATH(
+            { APerformanceHint_sendHint(session.get(), static_cast<SessionHint>(-1)); },
+            "invalid session hint");
 
     Mock::VerifyAndClearExpectations(mMockSession.get());
     for (int i = 0; i < mMaxLoadHintsPerInterval; ++i) {
-        APerformanceHint_sendHint(session, hintId);
+        APerformanceHint_sendHint(session.get(), hintId);
     }
 
     // Expect to get rate limited if we try to send faster than the limiter allows
     EXPECT_CALL(*mMockSession, sendHint(_)).Times(Exactly(0));
-    result = APerformanceHint_notifyWorkloadIncrease(session, true, true, "Test hint");
+    result = APerformanceHint_notifyWorkloadIncrease(session.get(), true, true, "Test hint");
     EXPECT_EQ(result, EBUSY);
     EXPECT_CALL(*mMockSession, sendHint(_)).Times(Exactly(0));
-    result = APerformanceHint_notifyWorkloadReset(session, true, true, "Test hint");
+    result = APerformanceHint_notifyWorkloadReset(session.get(), true, true, "Test hint");
     EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
-    APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, TestUpdatedSessionCreation) {
     EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)).Times(1);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
-    APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, TestSessionCreationUsingConfig) {
     EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, _, _, _, _)).Times(1);
-    SessionCreationConfig config{.tids = std::vector<int32_t>(1, 2),
-                                 .targetWorkDurationNanos = 5678,
-                                 .modesToEnable = std::vector<hal::SessionMode>(0)};
+    auto&& config = configFromCreator({.tids = mTids});
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSessionUsingConfig(manager, config);
+    auto&& session = createSessionUsingConfig(manager, config);
     ASSERT_TRUE(session);
-    APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, TestHwuiSessionCreation) {
     EXPECT_CALL(*mMockIHintManager, createHintSessionWithConfig(_, hal::SessionTag::HWUI, _, _, _))
             .Times(1);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager, 56789L, true);
+    auto&& session = createSession(manager, 56789L, true);
     ASSERT_TRUE(session);
-    APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, SetThreads) {
     APerformanceHintManager* manager = createManager();
 
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
 
     int32_t emptyTids[2];
-    int result = APerformanceHint_setThreads(session, emptyTids, 0);
+    int result = APerformanceHint_setThreads(session.get(), emptyTids, 0);
     EXPECT_EQ(EINVAL, result);
 
     std::vector<int32_t> newTids;
     newTids.push_back(1);
     newTids.push_back(3);
     EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(newTids))).Times(Exactly(1));
-    result = APerformanceHint_setThreads(session, newTids.data(), newTids.size());
+    result = APerformanceHint_setThreads(session.get(), newTids.data(), newTids.size());
     EXPECT_EQ(0, result);
 
     testing::Mock::VerifyAndClearExpectations(mMockIHintManager.get());
@@ -383,27 +453,27 @@
     EXPECT_CALL(*mMockIHintManager, setHintSessionThreads(_, Eq(invalidTids)))
             .Times(Exactly(1))
             .WillOnce(Return(ByMove(ScopedAStatus::fromExceptionCode(EX_SECURITY))));
-    result = APerformanceHint_setThreads(session, invalidTids.data(), invalidTids.size());
+    result = APerformanceHint_setThreads(session.get(), invalidTids.data(), invalidTids.size());
     EXPECT_EQ(EPERM, result);
 }
 
 TEST_F(PerformanceHintTest, SetPowerEfficient) {
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
 
     EXPECT_CALL(*mMockSession, setMode(_, Eq(true))).Times(Exactly(1));
-    int result = APerformanceHint_setPreferPowerEfficiency(session, true);
+    int result = APerformanceHint_setPreferPowerEfficiency(session.get(), true);
     EXPECT_EQ(0, result);
 
     EXPECT_CALL(*mMockSession, setMode(_, Eq(false))).Times(Exactly(1));
-    result = APerformanceHint_setPreferPowerEfficiency(session, false);
+    result = APerformanceHint_setPreferPowerEfficiency(session.get(), false);
     EXPECT_EQ(0, result);
 }
 
 TEST_F(PerformanceHintTest, CreateZeroTargetDurationSession) {
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager, 0);
+    auto&& session = createSession(manager, 0);
     ASSERT_TRUE(session);
 }
 
@@ -428,12 +498,12 @@
 
 TEST_F(PerformanceHintTest, TestAPerformanceHint_reportActualWorkDuration2) {
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
 
     int64_t targetDurationNanos = 10;
     EXPECT_CALL(*mMockSession, updateTargetWorkDuration(Eq(targetDurationNanos))).Times(Exactly(1));
-    int result = APerformanceHint_updateTargetWorkDuration(session, targetDurationNanos);
+    int result = APerformanceHint_updateTargetWorkDuration(session.get(), targetDurationNanos);
     EXPECT_EQ(0, result);
 
     usleep(2); // Sleep for longer than preferredUpdateRateNanos.
@@ -452,54 +522,53 @@
 
         EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
                 .Times(Exactly(pair.expectedResult == OK));
-        result = APerformanceHint_reportActualWorkDuration2(session,
+        result = APerformanceHint_reportActualWorkDuration2(session.get(),
                                                             reinterpret_cast<AWorkDuration*>(
                                                                     &pair.duration));
         EXPECT_EQ(pair.expectedResult, result);
     }
 
     EXPECT_CALL(*mMockSession, close()).Times(Exactly(1));
-    APerformanceHint_closeSession(session);
 }
 
 TEST_F(PerformanceHintTest, TestAWorkDuration) {
-    AWorkDuration* aWorkDuration = AWorkDuration_create();
+    // AWorkDuration* aWorkDuration = AWorkDuration_create();
+    auto&& aWorkDuration = wrapWorkDuration(AWorkDuration_create());
     ASSERT_NE(aWorkDuration, nullptr);
 
-    AWorkDuration_setWorkPeriodStartTimestampNanos(aWorkDuration, 1);
-    AWorkDuration_setActualTotalDurationNanos(aWorkDuration, 20);
-    AWorkDuration_setActualCpuDurationNanos(aWorkDuration, 13);
-    AWorkDuration_setActualGpuDurationNanos(aWorkDuration, 8);
-    AWorkDuration_release(aWorkDuration);
+    AWorkDuration_setWorkPeriodStartTimestampNanos(aWorkDuration.get(), 1);
+    AWorkDuration_setActualTotalDurationNanos(aWorkDuration.get(), 20);
+    AWorkDuration_setActualCpuDurationNanos(aWorkDuration.get(), 13);
+    AWorkDuration_setActualGpuDurationNanos(aWorkDuration.get(), 8);
 }
 
 TEST_F(PerformanceHintTest, TestCreateUsingFMQ) {
     setFMQEnabled(true);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     ASSERT_TRUE(session);
 }
 
 TEST_F(PerformanceHintTest, TestUpdateTargetWorkDurationUsingFMQ) {
     setFMQEnabled(true);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
-    APerformanceHint_updateTargetWorkDuration(session, 456);
+    auto&& session = createSession(manager);
+    APerformanceHint_updateTargetWorkDuration(session.get(), 456);
     expectToReadFromFmq<HalChannelMessageContents::Tag::targetDuration>(456);
 }
 
 TEST_F(PerformanceHintTest, TestSendHintUsingFMQ) {
     setFMQEnabled(true);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
-    APerformanceHint_sendHint(session, SessionHint::CPU_LOAD_UP);
+    auto&& session = createSession(manager);
+    APerformanceHint_sendHint(session.get(), SessionHint::CPU_LOAD_UP);
     expectToReadFromFmq<HalChannelMessageContents::Tag::hint>(hal::SessionHint::CPU_LOAD_UP);
 }
 
 TEST_F(PerformanceHintTest, TestReportActualUsingFMQ) {
     setFMQEnabled(true);
     APerformanceHintManager* manager = createManager();
-    APerformanceHintSession* session = createSession(manager);
+    auto&& session = createSession(manager);
     hal::WorkDuration duration{.timeStampNanos = 3,
                                .durationNanos = 999999,
                                .workPeriodStartTimestampNanos = 1,
@@ -513,20 +582,91 @@
             .gpuDurationNanos = duration.gpuDurationNanos,
     };
 
-    APerformanceHint_reportActualWorkDuration2(session,
+    APerformanceHint_reportActualWorkDuration2(session.get(),
                                                reinterpret_cast<AWorkDuration*>(&duration));
     expectToReadFromFmq<HalChannelMessageContents::Tag::workDuration>(durationExpected);
 }
 
 TEST_F(PerformanceHintTest, TestASessionCreationConfig) {
-    ASessionCreationConfig* config = ASessionCreationConfig_create();
-    ASSERT_NE(config, nullptr);
+    auto&& config = configFromCreator({
+            .tids = mTids,
+            .targetDuration = 20,
+            .powerEfficient = true,
+            .graphicsPipeline = true,
+    });
 
-    const int32_t testTids[2] = {1, 2};
-    const size_t size = 2;
-    EXPECT_EQ(ASessionCreationConfig_setTids(config, testTids, size), 0);
-    EXPECT_EQ(ASessionCreationConfig_setTargetWorkDurationNanos(config, 20), 0);
-    EXPECT_EQ(ASessionCreationConfig_setPreferPowerEfficiency(config, true), 0);
-    EXPECT_EQ(ASessionCreationConfig_setGraphicsPipeline(config, true), 0);
-    ASessionCreationConfig_release(config);
+    APerformanceHintManager* manager = createManager();
+    auto&& session = createSessionUsingConfig(manager, config);
+
+    ASSERT_NE(session, nullptr);
+    ASSERT_NE(config, nullptr);
+}
+
+TEST_F(PerformanceHintTest, TestSupportObject) {
+    // Disable GPU and Power Efficiency support to test partial enabling
+    mClientData.supportInfo.sessionModes &= ~(1 << (int)hal::SessionMode::AUTO_GPU);
+    mClientData.supportInfo.sessionHints &= ~(1 << (int)hal::SessionHint::GPU_LOAD_UP);
+    mClientData.supportInfo.sessionHints &= ~(1 << (int)hal::SessionHint::POWER_EFFICIENCY);
+
+    APerformanceHintManager* manager = createManager();
+
+    union {
+        int expectedSupportInt;
+        SupportHelper expectedSupport;
+    };
+
+    union {
+        int actualSupportInt;
+        SupportHelper actualSupport;
+    };
+
+    expectedSupport = getFullySupportedSupportHelper();
+    actualSupport = getSupportHelper();
+
+    expectedSupport.autoGpu = false;
+
+    EXPECT_EQ(expectedSupportInt, actualSupportInt);
+}
+
+TEST_F(PerformanceHintTest, TestCreatingAutoSession) {
+    // Disable GPU capability for testing
+    mClientData.supportInfo.sessionModes &= ~(1 << (int)hal::SessionMode::AUTO_GPU);
+    APerformanceHintManager* manager = createManager();
+
+    auto&& invalidConfig = configFromCreator({
+            .tids = mTids,
+            .targetDuration = 20,
+            .graphicsPipeline = false,
+            .autoCpu = true,
+            .autoGpu = true,
+    });
+
+    EXPECT_DEATH({ createSessionUsingConfig(manager, invalidConfig); }, "");
+
+    auto&& unsupportedConfig = configFromCreator({
+            .tids = mTids,
+            .targetDuration = 20,
+            .graphicsPipeline = true,
+            .autoCpu = true,
+            .autoGpu = true,
+    });
+
+    APerformanceHintSession* unsupportedSession = nullptr;
+
+    // Creating a session with auto timing but no graphics pipeline should fail
+    int out = APerformanceHint_createSessionUsingConfig(manager, unsupportedConfig.get(),
+                                                        &unsupportedSession);
+    EXPECT_EQ(out, ENOTSUP);
+    EXPECT_EQ(wrapSession(unsupportedSession), nullptr);
+
+    auto&& validConfig = configFromCreator({
+            .tids = mTids,
+            .targetDuration = 20,
+            .graphicsPipeline = true,
+            .autoCpu = true,
+            .autoGpu = false,
+    });
+
+    auto&& validSession = createSessionUsingConfig(manager, validConfig);
+    EXPECT_NE(validSession, nullptr);
 }
diff --git a/nfc/Android.bp b/nfc/Android.bp
deleted file mode 100644
index 0fdb3bd..0000000
--- a/nfc/Android.bp
+++ /dev/null
@@ -1,79 +0,0 @@
-package {
-    default_team: "trendy_team_fwk_nfc",
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
-    name: "framework-nfc-updatable-sources",
-    path: "java",
-    srcs: [
-        "java/**/*.java",
-        "java/**/*.aidl",
-    ],
-    visibility: [
-        "//frameworks/base:__subpackages__",
-        "//packages/apps/Nfc:__subpackages__",
-        "//packages/modules/Nfc:__subpackages__",
-    ],
-}
-
-java_sdk_library {
-    name: "framework-nfc",
-    libs: [
-        "androidx.annotation_annotation",
-        "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
-        "framework-permission-s.stubs.module_lib",
-        "framework-permission.stubs.module_lib",
-    ],
-    stub_only_libs: [
-        // Needed for javadoc references.
-        "framework-permission-s.stubs.module_lib",
-    ],
-    static_libs: [
-        "android.nfc.flags-aconfig-java",
-        "android.permission.flags-aconfig-java",
-    ],
-    srcs: [
-        ":framework-nfc-updatable-sources",
-        ":framework-nfc-javastream-protos",
-    ],
-    defaults: ["framework-module-defaults"],
-    sdk_version: "module_current",
-    min_sdk_version: "35", // Make it 36 once available.
-    installable: true,
-    optimize: {
-        enabled: false,
-    },
-    hostdex: true, // for hiddenapi check
-    permitted_packages: [
-        "android.nfc",
-        "com.android.nfc",
-    ],
-    impl_library_visibility: [
-        "//frameworks/base:__subpackages__",
-        "//cts:__subpackages__",
-        "//packages/apps/Nfc:__subpackages__",
-        "//packages/modules/Nfc:__subpackages__",
-    ],
-    jarjar_rules: ":nfc-jarjar-rules",
-    lint: {
-        baseline_filename: "lint-baseline.xml",
-    },
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.nfcservices",
-    ],
-    aconfig_declarations: [
-        "android.nfc.flags-aconfig",
-    ],
-}
-
-filegroup {
-    name: "nfc-jarjar-rules",
-    srcs: ["jarjar-rules.txt"],
-}
diff --git a/nfc/OWNERS b/nfc/OWNERS
deleted file mode 100644
index f46dccd..0000000
--- a/nfc/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
\ No newline at end of file
diff --git a/nfc/TEST_MAPPING b/nfc/TEST_MAPPING
deleted file mode 100644
index 49c778d..0000000
--- a/nfc/TEST_MAPPING
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "presubmit": [
-    {
-      "name": "NfcManagerTests"
-    },
-    {
-      "name": "CtsNfcTestCases"
-    },
-    {
-      "name": "CtsNdefTestCases"
-    }
-  ]
-}
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
deleted file mode 100644
index c8c479a..0000000
--- a/nfc/api/current.txt
+++ /dev/null
@@ -1,495 +0,0 @@
-// Signature format: 2.0
-package android.nfc {
-
-  public final class AvailableNfcAntenna implements android.os.Parcelable {
-    ctor public AvailableNfcAntenna(int, int);
-    method public int describeContents();
-    method public int getLocationX();
-    method public int getLocationY();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.AvailableNfcAntenna> CREATOR;
-  }
-
-  public class FormatException extends java.lang.Exception {
-    ctor public FormatException();
-    ctor public FormatException(String);
-    ctor public FormatException(String, Throwable);
-  }
-
-  public final class NdefMessage implements android.os.Parcelable {
-    ctor public NdefMessage(byte[]) throws android.nfc.FormatException;
-    ctor public NdefMessage(android.nfc.NdefRecord, android.nfc.NdefRecord...);
-    ctor public NdefMessage(android.nfc.NdefRecord[]);
-    method public int describeContents();
-    method public int getByteArrayLength();
-    method public android.nfc.NdefRecord[] getRecords();
-    method public byte[] toByteArray();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefMessage> CREATOR;
-  }
-
-  public final class NdefRecord implements android.os.Parcelable {
-    ctor public NdefRecord(short, byte[], byte[], byte[]);
-    ctor @Deprecated public NdefRecord(byte[]) throws android.nfc.FormatException;
-    method public static android.nfc.NdefRecord createApplicationRecord(String);
-    method public static android.nfc.NdefRecord createExternal(String, String, byte[]);
-    method public static android.nfc.NdefRecord createMime(String, byte[]);
-    method public static android.nfc.NdefRecord createTextRecord(String, String);
-    method public static android.nfc.NdefRecord createUri(android.net.Uri);
-    method public static android.nfc.NdefRecord createUri(String);
-    method public int describeContents();
-    method public byte[] getId();
-    method public byte[] getPayload();
-    method public short getTnf();
-    method public byte[] getType();
-    method @Deprecated public byte[] toByteArray();
-    method public String toMimeType();
-    method public android.net.Uri toUri();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NdefRecord> CREATOR;
-    field public static final byte[] RTD_ALTERNATIVE_CARRIER;
-    field public static final byte[] RTD_HANDOVER_CARRIER;
-    field public static final byte[] RTD_HANDOVER_REQUEST;
-    field public static final byte[] RTD_HANDOVER_SELECT;
-    field public static final byte[] RTD_SMART_POSTER;
-    field public static final byte[] RTD_TEXT;
-    field public static final byte[] RTD_URI;
-    field public static final short TNF_ABSOLUTE_URI = 3; // 0x3
-    field public static final short TNF_EMPTY = 0; // 0x0
-    field public static final short TNF_EXTERNAL_TYPE = 4; // 0x4
-    field public static final short TNF_MIME_MEDIA = 2; // 0x2
-    field public static final short TNF_UNCHANGED = 6; // 0x6
-    field public static final short TNF_UNKNOWN = 5; // 0x5
-    field public static final short TNF_WELL_KNOWN = 1; // 0x1
-  }
-
-  public final class NfcAdapter {
-    method @FlaggedApi("android.nfc.nfc_state_change") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable();
-    method public void disableForegroundDispatch(android.app.Activity);
-    method public void disableReaderMode(android.app.Activity);
-    method @FlaggedApi("android.nfc.nfc_state_change") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enable();
-    method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
-    method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
-    method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
-    method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
-    method @FlaggedApi("android.nfc.enable_nfc_charging") @Nullable public android.nfc.WlcListenerDeviceInfo getWlcListenerDeviceInfo();
-    method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
-    method public boolean isEnabled();
-    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeEnabled();
-    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported();
-    method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
-    method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
-    method public boolean isSecureNfcEnabled();
-    method public boolean isSecureNfcSupported();
-    method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAllowed();
-    method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAppPreferenceSupported();
-    method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled();
-    method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity);
-    method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int);
-    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setObserveModeEnabled(boolean);
-    field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED";
-    field @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE = "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE";
-    field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
-    field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
-    field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
-    field public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
-    field @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT) public static final String ACTION_TRANSACTION_DETECTED = "android.nfc.action.TRANSACTION_DETECTED";
-    field public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
-    field public static final String EXTRA_AID = "android.nfc.extra.AID";
-    field public static final String EXTRA_DATA = "android.nfc.extra.DATA";
-    field public static final String EXTRA_ID = "android.nfc.extra.ID";
-    field public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
-    field public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON = "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
-    field public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
-    field public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
-    field public static final String EXTRA_TAG = "android.nfc.extra.TAG";
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_DISABLE = 0; // 0x0
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_KEEP = -2147483648; // 0x80000000
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_A = 1; // 0x1
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_B = 2; // 0x2
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_LISTEN_NFC_PASSIVE_F = 4; // 0x4
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_DISABLE = 0; // 0x0
-    field @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public static final int FLAG_READER_KEEP = -2147483648; // 0x80000000
-    field public static final int FLAG_READER_NFC_A = 1; // 0x1
-    field public static final int FLAG_READER_NFC_B = 2; // 0x2
-    field public static final int FLAG_READER_NFC_BARCODE = 16; // 0x10
-    field public static final int FLAG_READER_NFC_F = 4; // 0x4
-    field public static final int FLAG_READER_NFC_V = 8; // 0x8
-    field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100
-    field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80
-    field public static final int PREFERRED_PAYMENT_CHANGED = 2; // 0x2
-    field public static final int PREFERRED_PAYMENT_LOADED = 1; // 0x1
-    field public static final int PREFERRED_PAYMENT_UPDATED = 3; // 0x3
-    field public static final int STATE_OFF = 1; // 0x1
-    field public static final int STATE_ON = 3; // 0x3
-    field public static final int STATE_TURNING_OFF = 4; // 0x4
-    field public static final int STATE_TURNING_ON = 2; // 0x2
-  }
-
-  @Deprecated public static interface NfcAdapter.CreateBeamUrisCallback {
-    method @Deprecated public android.net.Uri[] createBeamUris(android.nfc.NfcEvent);
-  }
-
-  @Deprecated public static interface NfcAdapter.CreateNdefMessageCallback {
-    method @Deprecated public android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent);
-  }
-
-  @Deprecated public static interface NfcAdapter.OnNdefPushCompleteCallback {
-    method @Deprecated public void onNdefPushComplete(android.nfc.NfcEvent);
-  }
-
-  public static interface NfcAdapter.OnTagRemovedListener {
-    method public void onTagRemoved();
-  }
-
-  public static interface NfcAdapter.ReaderCallback {
-    method public void onTagDiscovered(android.nfc.Tag);
-  }
-
-  public final class NfcAntennaInfo implements android.os.Parcelable {
-    ctor public NfcAntennaInfo(int, int, boolean, @NonNull java.util.List<android.nfc.AvailableNfcAntenna>);
-    method public int describeContents();
-    method @NonNull public java.util.List<android.nfc.AvailableNfcAntenna> getAvailableNfcAntennas();
-    method public int getDeviceHeight();
-    method public int getDeviceWidth();
-    method public boolean isDeviceFoldable();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.NfcAntennaInfo> CREATOR;
-  }
-
-  public final class NfcEvent {
-    field public final android.nfc.NfcAdapter nfcAdapter;
-    field public final int peerLlcpMajorVersion;
-    field public final int peerLlcpMinorVersion;
-  }
-
-  public final class NfcManager {
-    method public android.nfc.NfcAdapter getDefaultAdapter();
-  }
-
-  public final class Tag implements android.os.Parcelable {
-    method public int describeContents();
-    method public byte[] getId();
-    method public String[] getTechList();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.Tag> CREATOR;
-  }
-
-  public class TagLostException extends java.io.IOException {
-    ctor public TagLostException();
-    ctor public TagLostException(String);
-  }
-
-  @FlaggedApi("android.nfc.enable_nfc_charging") public final class WlcListenerDeviceInfo implements android.os.Parcelable {
-    ctor public WlcListenerDeviceInfo(int, double, double, int);
-    method public int describeContents();
-    method @FloatRange(from=0.0, to=100.0) public double getBatteryLevel();
-    method public int getProductId();
-    method public int getState();
-    method public double getTemperature();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.WlcListenerDeviceInfo> CREATOR;
-    field public static final int STATE_CONNECTED_CHARGING = 2; // 0x2
-    field public static final int STATE_CONNECTED_DISCHARGING = 3; // 0x3
-    field public static final int STATE_DISCONNECTED = 1; // 0x1
-  }
-
-}
-
-package android.nfc.cardemulation {
-
-  public final class CardEmulation {
-    method public boolean categoryAllowsForegroundPreference(String);
-    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
-    method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
-    method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public int getDefaultNfcSubscriptionId();
-    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService();
-    method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
-    method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
-    method public int getSelectionModeForCategory(String);
-    method public boolean isDefaultServiceForAid(android.content.ComponentName, String);
-    method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
-    method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public boolean isEuiccSupported();
-    method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public void registerNfcEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
-    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
-    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
-    method public boolean removeAidsForService(android.content.ComponentName, String);
-    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String);
-    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean removePollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
-    method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
-    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setShouldDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean);
-    method public boolean supportsAidPrefixRegistration();
-    method @FlaggedApi("android.nfc.nfc_event_listener") public void unregisterNfcEventCallback(@NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
-    method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
-    method public boolean unsetPreferredService(android.app.Activity);
-    field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
-    field public static final String CATEGORY_OTHER = "other";
-    field public static final String CATEGORY_PAYMENT = "payment";
-    field public static final String EXTRA_CATEGORY = "category";
-    field public static final String EXTRA_SERVICE_COMPONENT = "component";
-    field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_COMMAND_TIMEOUT = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY = "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY";
-    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET = -1; // 0xffffffff
-    field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
-    field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
-    field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
-  }
-
-  @FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventCallback {
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidConflictOccurred(@NonNull String);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidNotRouted(@NonNull String);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onInternalErrorReported(int);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onNfcStateChanged(int);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onObserveModeStateChanged(boolean);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onPreferredServiceChanged(boolean);
-    method @FlaggedApi("android.nfc.nfc_event_listener") public default void onRemoteFieldChanged(boolean);
-  }
-
-  public abstract class HostApduService extends android.app.Service {
-    ctor public HostApduService();
-    method public final void notifyUnhandled();
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract void onDeactivated(int);
-    method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
-    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.nfc.cardemulation.PollingFrame>);
-    method public final void sendResponseApdu(byte[]);
-    field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
-    field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
-    field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
-    field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service";
-  }
-
-  public abstract class HostNfcFService extends android.app.Service {
-    ctor public HostNfcFService();
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public abstract void onDeactivated(int);
-    method public abstract byte[] processNfcFPacket(byte[], android.os.Bundle);
-    method public final void sendResponsePacket(byte[]);
-    field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
-    field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_NFCF_SERVICE";
-    field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_nfcf_service";
-  }
-
-  public final class NfcFCardEmulation {
-    method public boolean disableService(android.app.Activity) throws java.lang.RuntimeException;
-    method public boolean enableService(android.app.Activity, android.content.ComponentName) throws java.lang.RuntimeException;
-    method public static android.nfc.cardemulation.NfcFCardEmulation getInstance(android.nfc.NfcAdapter);
-    method public String getNfcid2ForService(android.content.ComponentName) throws java.lang.RuntimeException;
-    method public String getSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
-    method public boolean registerSystemCodeForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
-    method public boolean setNfcid2ForService(android.content.ComponentName, String) throws java.lang.RuntimeException;
-    method public boolean unregisterSystemCodeForService(android.content.ComponentName) throws java.lang.RuntimeException;
-  }
-
-  public abstract class OffHostApduService extends android.app.Service {
-    ctor public OffHostApduService();
-    field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE";
-    field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.off_host_apdu_service";
-  }
-
-  @FlaggedApi("android.nfc.nfc_read_polling_loop") public final class PollingFrame implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public byte[] getData();
-    method public long getTimestamp();
-    method public boolean getTriggeredAutoTransact();
-    method public int getType();
-    method public int getVendorSpecificGain();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.PollingFrame> CREATOR;
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_A = 65; // 0x41
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_B = 66; // 0x42
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_F = 70; // 0x46
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_OFF = 88; // 0x58
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_ON = 79; // 0x4f
-    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x55
-  }
-
-}
-
-package android.nfc.tech {
-
-  public final class IsoDep implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.IsoDep get(android.nfc.Tag);
-    method public byte[] getHiLayerResponse();
-    method public byte[] getHistoricalBytes();
-    method public int getMaxTransceiveLength();
-    method public android.nfc.Tag getTag();
-    method public int getTimeout();
-    method public boolean isConnected();
-    method public boolean isExtendedLengthApduSupported();
-    method public void setTimeout(int);
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-  }
-
-  public final class MifareClassic implements android.nfc.tech.TagTechnology {
-    method public boolean authenticateSectorWithKeyA(int, byte[]) throws java.io.IOException;
-    method public boolean authenticateSectorWithKeyB(int, byte[]) throws java.io.IOException;
-    method public int blockToSector(int);
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public void decrement(int, int) throws java.io.IOException;
-    method public static android.nfc.tech.MifareClassic get(android.nfc.Tag);
-    method public int getBlockCount();
-    method public int getBlockCountInSector(int);
-    method public int getMaxTransceiveLength();
-    method public int getSectorCount();
-    method public int getSize();
-    method public android.nfc.Tag getTag();
-    method public int getTimeout();
-    method public int getType();
-    method public void increment(int, int) throws java.io.IOException;
-    method public boolean isConnected();
-    method public byte[] readBlock(int) throws java.io.IOException;
-    method public void restore(int) throws java.io.IOException;
-    method public int sectorToBlock(int);
-    method public void setTimeout(int);
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-    method public void transfer(int) throws java.io.IOException;
-    method public void writeBlock(int, byte[]) throws java.io.IOException;
-    field public static final int BLOCK_SIZE = 16; // 0x10
-    field public static final byte[] KEY_DEFAULT;
-    field public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY;
-    field public static final byte[] KEY_NFC_FORUM;
-    field public static final int SIZE_1K = 1024; // 0x400
-    field public static final int SIZE_2K = 2048; // 0x800
-    field public static final int SIZE_4K = 4096; // 0x1000
-    field public static final int SIZE_MINI = 320; // 0x140
-    field public static final int TYPE_CLASSIC = 0; // 0x0
-    field public static final int TYPE_PLUS = 1; // 0x1
-    field public static final int TYPE_PRO = 2; // 0x2
-    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public final class MifareUltralight implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.MifareUltralight get(android.nfc.Tag);
-    method public int getMaxTransceiveLength();
-    method public android.nfc.Tag getTag();
-    method public int getTimeout();
-    method public int getType();
-    method public boolean isConnected();
-    method public byte[] readPages(int) throws java.io.IOException;
-    method public void setTimeout(int);
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-    method public void writePage(int, byte[]) throws java.io.IOException;
-    field public static final int PAGE_SIZE = 4; // 0x4
-    field public static final int TYPE_ULTRALIGHT = 1; // 0x1
-    field public static final int TYPE_ULTRALIGHT_C = 2; // 0x2
-    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public final class Ndef implements android.nfc.tech.TagTechnology {
-    method public boolean canMakeReadOnly();
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.Ndef get(android.nfc.Tag);
-    method public android.nfc.NdefMessage getCachedNdefMessage();
-    method public int getMaxSize();
-    method public android.nfc.NdefMessage getNdefMessage() throws android.nfc.FormatException, java.io.IOException;
-    method public android.nfc.Tag getTag();
-    method public String getType();
-    method public boolean isConnected();
-    method public boolean isWritable();
-    method public boolean makeReadOnly() throws java.io.IOException;
-    method public void writeNdefMessage(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
-    field public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
-    field public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
-    field public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
-    field public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
-    field public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
-  }
-
-  public final class NdefFormatable implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public void format(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
-    method public void formatReadOnly(android.nfc.NdefMessage) throws android.nfc.FormatException, java.io.IOException;
-    method public static android.nfc.tech.NdefFormatable get(android.nfc.Tag);
-    method public android.nfc.Tag getTag();
-    method public boolean isConnected();
-  }
-
-  public final class NfcA implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.NfcA get(android.nfc.Tag);
-    method public byte[] getAtqa();
-    method public int getMaxTransceiveLength();
-    method public short getSak();
-    method public android.nfc.Tag getTag();
-    method public int getTimeout();
-    method public boolean isConnected();
-    method public void setTimeout(int);
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-  }
-
-  public final class NfcB implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.NfcB get(android.nfc.Tag);
-    method public byte[] getApplicationData();
-    method public int getMaxTransceiveLength();
-    method public byte[] getProtocolInfo();
-    method public android.nfc.Tag getTag();
-    method public boolean isConnected();
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-  }
-
-  public final class NfcBarcode implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
-    method public byte[] getBarcode();
-    method public android.nfc.Tag getTag();
-    method public int getType();
-    method public boolean isConnected();
-    field public static final int TYPE_KOVIO = 1; // 0x1
-    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
-  }
-
-  public final class NfcF implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.NfcF get(android.nfc.Tag);
-    method public byte[] getManufacturer();
-    method public int getMaxTransceiveLength();
-    method public byte[] getSystemCode();
-    method public android.nfc.Tag getTag();
-    method public int getTimeout();
-    method public boolean isConnected();
-    method public void setTimeout(int);
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-  }
-
-  public final class NfcV implements android.nfc.tech.TagTechnology {
-    method public void close() throws java.io.IOException;
-    method public void connect() throws java.io.IOException;
-    method public static android.nfc.tech.NfcV get(android.nfc.Tag);
-    method public byte getDsfId();
-    method public int getMaxTransceiveLength();
-    method public byte getResponseFlags();
-    method public android.nfc.Tag getTag();
-    method public boolean isConnected();
-    method public byte[] transceive(byte[]) throws java.io.IOException;
-  }
-
-  public interface TagTechnology extends java.io.Closeable {
-    method public void connect() throws java.io.IOException;
-    method public android.nfc.Tag getTag();
-    method public boolean isConnected();
-  }
-
-}
-
diff --git a/nfc/api/lint-baseline.txt b/nfc/api/lint-baseline.txt
deleted file mode 100644
index ef9aab6..0000000
--- a/nfc/api/lint-baseline.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-// Baseline format: 1.0
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
-    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
-    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
-    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
-
-
-MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent):
-    Missing nullability on method `onBind` return
-MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent) parameter #0:
-    Missing nullability on parameter `intent` in method `onBind`
-
-
-RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
-    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
-    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
-    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
-    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
-    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
-    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
-    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
-    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
-    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
-    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
-    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
-    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
-    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
-    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
-    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
-    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#isWritable():
-    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
-    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
-    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
-    Method 'format' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
-    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#close():
-    Method 'close' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#connect():
-    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
diff --git a/nfc/api/module-lib-current.txt b/nfc/api/module-lib-current.txt
deleted file mode 100644
index 5ebe911..0000000
--- a/nfc/api/module-lib-current.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-// Signature format: 2.0
-package android.nfc {
-
-  public class NfcFrameworkInitializer {
-    method public static void registerServiceWrappers();
-    method public static void setNfcServiceManager(@NonNull android.nfc.NfcServiceManager);
-  }
-
-}
-
diff --git a/nfc/api/module-lib-lint-baseline.txt b/nfc/api/module-lib-lint-baseline.txt
deleted file mode 100644
index f7f8ee3..0000000
--- a/nfc/api/module-lib-lint-baseline.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-// Baseline format: 1.0
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
-    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
-    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
-    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
-    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
-
-RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
-    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
-    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
-    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
-    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
-    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
-    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
-    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
-    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
-    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
-    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
-    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
-    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
-    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
-    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
-    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
-    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#isWritable():
-    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
-    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
-    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
-    Method 'format' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
-    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#close():
-    Method 'close' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#connect():
-    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
-
-SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
-    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/nfc/api/module-lib-removed.txt b/nfc/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/nfc/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/nfc/api/removed.txt b/nfc/api/removed.txt
deleted file mode 100644
index fb82b5d..0000000
--- a/nfc/api/removed.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-// Signature format: 2.0
-package android.nfc {
-
-  public final class NfcAdapter {
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void disableForegroundNdefPush(android.app.Activity);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public boolean invokeBeam(android.app.Activity);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public boolean isNdefPushEnabled();
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setBeamPushUris(android.net.Uri[], android.app.Activity);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, android.app.Activity...);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...);
-    method @Deprecated @android.compat.annotation.UnsupportedAppUsage public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...);
-  }
-
-}
-
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
deleted file mode 100644
index 6bd6072..0000000
--- a/nfc/api/system-current.txt
+++ /dev/null
@@ -1,256 +0,0 @@
-// Signature format: 2.0
-package android.nfc {
-
-  public final class NfcAdapter {
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean addNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler, String[]);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disable(boolean);
-    method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
-    method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public android.nfc.NfcOemExtension getNfcOemExtension();
-    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int);
-    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
-    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
-    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
-    method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerNfcVendorNciCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
-    method @FlaggedApi("android.nfc.enable_nfc_charging") public void registerWlcStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.WlcStateListener);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
-    method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int sendVendorNciMessage(int, @IntRange(from=0, to=15) int, @IntRange(from=0) int, @NonNull byte[]);
-    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
-    method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderModePollingEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean);
-    method @FlaggedApi("android.nfc.enable_nfc_charging") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setWlcEnabled(boolean);
-    method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener);
-    method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterNfcVendorNciCallback(@NonNull android.nfc.NfcAdapter.NfcVendorNciCallback);
-    method @FlaggedApi("android.nfc.enable_nfc_charging") public void unregisterWlcStateListener(@NonNull android.nfc.NfcAdapter.WlcStateListener);
-    field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC = "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
-    field @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.SHOW_CUSTOMIZED_RESOLVER) public static final String ACTION_SHOW_NFC_RESOLVER = "android.nfc.action.SHOW_NFC_RESOLVER";
-    field @FlaggedApi("android.nfc.enable_nfc_mainline") public static final String EXTRA_RESOLVE_INFOS = "android.nfc.extra.RESOLVE_INFOS";
-    field @FlaggedApi("android.nfc.nfc_set_default_disc_tech") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static final int FLAG_SET_DEFAULT_TECH = 1073741824; // 0x40000000
-    field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int MESSAGE_TYPE_COMMAND = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_vendor_cmd") public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0; // 0x0
-    field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff
-    field public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0; // 0x0
-    field public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2; // 0xfffffffe
-  }
-
-  public static interface NfcAdapter.ControllerAlwaysOnListener {
-    method public void onControllerAlwaysOnChanged(boolean);
-  }
-
-  public static interface NfcAdapter.NfcUnlockHandler {
-    method public boolean onUnlockAttempted(android.nfc.Tag);
-  }
-
-  @FlaggedApi("android.nfc.nfc_vendor_cmd") public static interface NfcAdapter.NfcVendorNciCallback {
-    method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciNotification(@IntRange(from=9, to=15) int, int, @NonNull byte[]);
-    method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciResponse(@IntRange(from=0, to=15) int, int, @NonNull byte[]);
-  }
-
-  @FlaggedApi("android.nfc.enable_nfc_charging") public static interface NfcAdapter.WlcStateListener {
-    method public void onWlcStateChanged(@NonNull android.nfc.WlcListenerDeviceInfo);
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int forceRoutingTableCommit();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getActiveNfceeList();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public long getMaxPausePollingTimeoutMills();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.List<android.nfc.NfcRoutingTableEntry> getRoutingTable();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public android.nfc.T4tNdefNfcee getT4tNdefNfcee();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean hasUserEnabledNfc();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAutoChangeEnabled();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagPresent();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overwriteRoutingTable(int, int, int, int);
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int pausePolling(long);
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback);
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int resumePolling();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAutoChangeEnabled(boolean);
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOnMode(int);
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void triggerInitialization();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback);
-    field public static final int COMMIT_ROUTING_STATUS_FAILED = 3; // 0x3
-    field public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6; // 0x6
-    field public static final int COMMIT_ROUTING_STATUS_OK = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int DISABLE = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_DEFAULT = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_EE = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_TRANSPARENT = 2; // 0x2
-    field public static final int HCE_ACTIVATE = 1; // 0x1
-    field public static final int HCE_DATA_TRANSFERRED = 2; // 0x2
-    field public static final int HCE_DEACTIVATE = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_A = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_B = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_F = 4; // 0x4
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_NONE = 0; // 0x0
-    field public static final int POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE = 2; // 0x2
-    field public static final int POLLING_STATE_CHANGE_SUCCEEDED = 1; // 0x1
-    field public static final int STATUS_OK = 0; // 0x0
-    field public static final int STATUS_UNKNOWN_ERROR = 1; // 0x1
-  }
-
-  public static interface NfcOemExtension.Callback {
-    method public void onApplyRouting(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onBootFinished(int);
-    method public void onBootStarted();
-    method public void onCardEmulationActivated(boolean);
-    method public void onDisableFinished(int);
-    method public void onDisableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onDisableStarted();
-    method public void onEeListenActivated(boolean);
-    method public void onEeUpdated();
-    method public void onEnableFinished(int);
-    method public void onEnableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onEnableStarted();
-    method public void onExtractOemPackages(@NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.util.List<java.lang.String>>);
-    method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>);
-    method public void onHceEventReceived(int);
-    method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String);
-    method public void onLaunchHceTapAgainDialog(@NonNull android.nfc.cardemulation.ApduServiceInfo, @NonNull String);
-    method public void onLogEventNotified(@NonNull android.nfc.OemLogItems);
-    method public void onNdefMessage(@NonNull android.nfc.Tag, @NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onReaderOptionChanged(boolean);
-    method public void onRfDiscoveryStarted(boolean);
-    method public void onRfFieldActivated(boolean);
-    method public void onRoutingChanged(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-    method public void onRoutingTableFull();
-    method public void onStateUpdated(int);
-    method public void onTagConnected(boolean);
-    method public void onTagDispatch(@NonNull java.util.function.Consumer<java.lang.Boolean>);
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public abstract class NfcRoutingTableEntry {
-    method public int getNfceeId();
-    method public int getRouteType();
-    method public int getType();
-    field public static final int TYPE_AID = 0; // 0x0
-    field public static final int TYPE_PROTOCOL = 1; // 0x1
-    field public static final int TYPE_SYSTEM_CODE = 3; // 0x3
-    field public static final int TYPE_TECHNOLOGY = 2; // 0x2
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public final class OemLogItems implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getAction();
-    method public int getCallingPid();
-    method @Nullable public byte[] getCommandApdu();
-    method public int getEvent();
-    method @Nullable public byte[] getResponseApdu();
-    method @Nullable public java.time.Instant getRfFieldEventTimeMillis();
-    method @Nullable public android.nfc.Tag getTag();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.OemLogItems> CREATOR;
-    field public static final int EVENT_DISABLE = 2; // 0x2
-    field public static final int EVENT_ENABLE = 1; // 0x1
-    field public static final int EVENT_UNSET = 0; // 0x0
-    field public static final int LOG_ACTION_HCE_DATA = 516; // 0x204
-    field public static final int LOG_ACTION_NFC_TOGGLE = 513; // 0x201
-    field public static final int LOG_ACTION_RF_FIELD_STATE_CHANGED = 1; // 0x1
-    field public static final int LOG_ACTION_SCREEN_STATE_CHANGED = 518; // 0x206
-    field public static final int LOG_ACTION_TAG_DETECTED = 3; // 0x3
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingStatus {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultIsoDepRoute();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultOffHostRoute();
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultRoute();
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingTableAidEntry extends android.nfc.NfcRoutingTableEntry {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public String getAid();
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingTableProtocolEntry extends android.nfc.NfcRoutingTableEntry {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") public int getProtocol();
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_ISO_DEP = 4; // 0x4
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_NDEF = 7; // 0x7
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_NFC_DEP = 5; // 0x5
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_T1T = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_T2T = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_T3T = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_T5T = 6; // 0x6
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_UNDETERMINED = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int PROTOCOL_UNSUPPORTED = -1; // 0xffffffff
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingTableSystemCodeEntry extends android.nfc.NfcRoutingTableEntry {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public byte[] getSystemCode();
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingTableTechnologyEntry extends android.nfc.NfcRoutingTableEntry {
-    method @FlaggedApi("android.nfc.nfc_oem_extension") public int getTechnology();
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_A = 0; // 0x0
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_B = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_F = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_UNSUPPORTED = -1; // 0xffffffff
-    field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int TECHNOLOGY_V = 3; // 0x3
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public final class T4tNdefNfcee {
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public int clearData();
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isOperationOngoing();
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isSupported();
-    method @Nullable @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public android.nfc.T4tNdefNfceeCcFileInfo readCcfile();
-    method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public byte[] readData(@IntRange(from=0, to=65535) int);
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @WorkerThread public int writeData(@IntRange(from=0, to=65535) int, @NonNull byte[]);
-    field public static final int CLEAR_DATA_FAILED_DEVICE_BUSY = -1; // 0xffffffff
-    field public static final int CLEAR_DATA_FAILED_INTERNAL = 0; // 0x0
-    field public static final int CLEAR_DATA_SUCCESS = 1; // 0x1
-    field public static final int WRITE_DATA_ERROR_CONNECTION_FAILED = -6; // 0xfffffffa
-    field public static final int WRITE_DATA_ERROR_DEVICE_BUSY = -9; // 0xfffffff7
-    field public static final int WRITE_DATA_ERROR_EMPTY_PAYLOAD = -7; // 0xfffffff9
-    field public static final int WRITE_DATA_ERROR_INTERNAL = -1; // 0xffffffff
-    field public static final int WRITE_DATA_ERROR_INVALID_FILE_ID = -4; // 0xfffffffc
-    field public static final int WRITE_DATA_ERROR_INVALID_LENGTH = -5; // 0xfffffffb
-    field public static final int WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED = -8; // 0xfffffff8
-    field public static final int WRITE_DATA_ERROR_NFC_NOT_ON = -3; // 0xfffffffd
-    field public static final int WRITE_DATA_ERROR_RF_ACTIVATED = -2; // 0xfffffffe
-    field public static final int WRITE_DATA_SUCCESS = 0; // 0x0
-  }
-
-  @FlaggedApi("android.nfc.nfc_oem_extension") public final class T4tNdefNfceeCcFileInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @IntRange(from=15, to=32767) public int getCcFileLength();
-    method @IntRange(from=0xffffffff, to=65535) public int getFileId();
-    method @IntRange(from=5, to=32767) public int getMaxSize();
-    method public int getVersion();
-    method public boolean isReadAllowed();
-    method public boolean isWriteAllowed();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.nfc.T4tNdefNfceeCcFileInfo> CREATOR;
-    field public static final int VERSION_2_0 = 32; // 0x20
-    field public static final int VERSION_3_0 = 48; // 0x30
-  }
-
-}
-
-package android.nfc.cardemulation {
-
-  public final class CardEmulation {
-    method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context);
-    method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
-    method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overrideRoutingTable(@NonNull android.app.Activity, int, int);
-    method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void recoverRoutingTable(@NonNull android.app.Activity);
-    method @FlaggedApi("android.nfc.enable_card_emulation_euicc") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setDefaultNfcSubscriptionId(int);
-    method @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setServiceEnabledForCategoryOther(@NonNull android.content.ComponentName, boolean);
-    field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3; // 0x3
-    field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1; // 0x1
-    field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2; // 0x2
-    field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4; // 0x4
-    field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_OK = 0; // 0x0
-    field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2; // 0x2
-    field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1; // 0x1
-    field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3; // 0x3
-    field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0; // 0x0
-    field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_UNKNOWN = -1; // 0xffffffff
-  }
-
-}
-
diff --git a/nfc/api/system-lint-baseline.txt b/nfc/api/system-lint-baseline.txt
deleted file mode 100644
index c7a6181..0000000
--- a/nfc/api/system-lint-baseline.txt
+++ /dev/null
@@ -1,119 +0,0 @@
-// Baseline format: 1.0
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
-    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
-    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
-    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
-BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
-    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
-
-
-CallbackMethodName: android.nfc.NfcOemExtension.Callback#shouldSkipRoutingChange():
-    Callback method names must follow the on<Something> style: shouldSkipRoutingChange
-
-
-MethodNameTense: android.nfc.NfcOemExtension.Callback#onEnable():
-    Unexpected tense; probably meant `enabled`, was `onEnable`
-
-
-MissingNullability: android.nfc.cardemulation.CardEmulation#overrideRoutingTable(android.app.Activity, String, String) parameter #1:
-    Missing nullability on parameter `protocol` in method `overrideRoutingTable`
-MissingNullability: android.nfc.cardemulation.CardEmulation#overrideRoutingTable(android.app.Activity, String, String) parameter #2:
-    Missing nullability on parameter `technology` in method `overrideRoutingTable`
-MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent):
-    Missing nullability on method `onBind` return
-MissingNullability: android.nfc.cardemulation.OffHostApduService#onBind(android.content.Intent) parameter #0:
-    Missing nullability on parameter `intent` in method `onBind`
-
-
-RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
-    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
-    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
-    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
-    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
-    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
-    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
-    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
-    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
-    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
-    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
-    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
-    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
-    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
-    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
-    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
-    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#isWritable():
-    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
-    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
-    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
-    Method 'format' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
-    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#getTimeout():
-    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
-    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
-    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#close():
-    Method 'close' documentation mentions permissions without declaring @RequiresPermission
-RequiresPermission: android.nfc.tech.TagTechnology#connect():
-    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
-
-
-SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
-    SAM-compatible parameters (such as parameter 2, "callback", in android.nfc.NfcAdapter.enableReaderMode) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
-    SAM-compatible parameters (such as parameter 3, "tagRemovedListener", in android.nfc.NfcAdapter.ignore) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-
-
-SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
-    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/nfc/api/system-removed.txt b/nfc/api/system-removed.txt
deleted file mode 100644
index c6eaa57..0000000
--- a/nfc/api/system-removed.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-// Signature format: 2.0
-package android.nfc {
-
-  public final class NfcAdapter {
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean disableNdefPush();
-    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableNdefPush();
-    method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
-    field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
-  }
-
-}
-
diff --git a/nfc/api/test-current.txt b/nfc/api/test-current.txt
deleted file mode 100644
index d802177..0000000
--- a/nfc/api/test-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/nfc/api/test-removed.txt b/nfc/api/test-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/nfc/api/test-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/nfc/jarjar-rules.txt b/nfc/jarjar-rules.txt
deleted file mode 100644
index 63a6a58..0000000
--- a/nfc/jarjar-rules.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-# Used by framework-nfc for proto debug dumping
-rule android.app.PendingIntentProto* com.android.nfc.x.@0
-rule android.content.ComponentNameProto* com.android.nfc.x.@0
-rule android.content.IntentProto* com.android.nfc.x.@0
-rule android.content.IntentFilterProto* com.android.nfc.x.@0
-rule android.content.AuthorityEntryProto* com.android.nfc.x.@0
-rule android.content.UriRelativeFilter* com.android.nfc.x.@0
-rule android.nfc.cardemulation.AidGroupProto* com.android.nfc.x.@0
-rule android.nfc.cardemulation.ApduServiceInfoProto* com.android.nfc.x.@0
-rule android.nfc.cardemulation.NfcFServiceInfoProto* com.android.nfc.x.@0
-rule android.nfc.NdefMessageProto* com.android.nfc.x.@0
-rule android.nfc.NdefRecordProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.CardEmulationManagerProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.RegisteredServicesCacheProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.RegisteredNfcFServicesCacheProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.PreferredServicesProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.EnabledNfcFServicesProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.RegisteredAidCacheProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.AidRoutingManagerProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.RegisteredT3tIdentifiersCacheProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.SystemCodeRoutingManagerProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.HostEmulationManagerProto* com.android.nfc.x.@0
-rule com.android.nfc.cardemulation.HostNfcFEmulationManagerProto* com.android.nfc.x.@0
-rule com.android.nfc.NfcServiceDumpProto* com.android.nfc.x.@0
-rule com.android.nfc.DiscoveryParamsProto* com.android.nfc.x.@0
-rule com.android.nfc.NfcDispatcherProto* com.android.nfc.x.@0
-rule android.os.PersistableBundleProto* com.android.nfc.x.@0
-
-# Used by framework-nfc for reading trunk stable flags
-rule android.nfc.*Flags* com.android.nfc.x.@0
-rule android.nfc.Flags com.android.nfc.x.@0
-rule android.permission.flags.** com.android.nfc.x.@0
-
-# Used by framework-nfc for misc utilities
-rule android.os.PatternMatcher* com.android.nfc.x.@0
-
-rule com.android.incident.Privacy* com.android.nfc.x.@0
-rule com.android.incident.PrivacyFlags* com.android.nfc.x.@0
diff --git a/nfc/java/android/nfc/ApduList.aidl b/nfc/java/android/nfc/ApduList.aidl
deleted file mode 100644
index f6236b2..0000000
--- a/nfc/java/android/nfc/ApduList.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable ApduList;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/ApduList.java b/nfc/java/android/nfc/ApduList.java
deleted file mode 100644
index 027141d..0000000
--- a/nfc/java/android/nfc/ApduList.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package android.nfc;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public class ApduList implements Parcelable {
-
-    private ArrayList<byte[]> commands = new ArrayList<byte[]>();
-
-    public ApduList() {
-    }
-
-    public void add(byte[] command) {
-        commands.add(command);
-    }
-
-    public List<byte[]> get() {
-        return commands;
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<ApduList> CREATOR =
-        new Parcelable.Creator<ApduList>() {
-        @Override
-        public ApduList createFromParcel(Parcel in) {
-            return new ApduList(in);
-        }
-
-        @Override
-        public ApduList[] newArray(int size) {
-            return new ApduList[size];
-        }
-    };
-
-    private ApduList(Parcel in) {
-        int count = in.readInt();
-
-        for (int i = 0 ; i < count ; i++) {
-
-            int length = in.readInt();
-            byte[] cmd = new byte[length];
-            in.readByteArray(cmd);
-            commands.add(cmd);
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(commands.size());
-
-        for (byte[] cmd : commands) {
-            dest.writeInt(cmd.length);
-            dest.writeByteArray(cmd);
-        }
-    }
-}
-
-
diff --git a/nfc/java/android/nfc/AvailableNfcAntenna.aidl b/nfc/java/android/nfc/AvailableNfcAntenna.aidl
deleted file mode 100644
index 9d06e2d..0000000
--- a/nfc/java/android/nfc/AvailableNfcAntenna.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable AvailableNfcAntenna;
diff --git a/nfc/java/android/nfc/AvailableNfcAntenna.java b/nfc/java/android/nfc/AvailableNfcAntenna.java
deleted file mode 100644
index e76aeb0..0000000
--- a/nfc/java/android/nfc/AvailableNfcAntenna.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents a single available Nfc antenna
- * on an Android device.
- */
-public final class AvailableNfcAntenna implements Parcelable {
-    /**
-     * Location of the antenna on the Y axis in millimeters.
-     * 0 is the top-left when the user is facing the screen
-     * and the device orientation is Portrait.
-     */
-    private final int mLocationX;
-    /**
-     * Location of the antenna on the Y axis in millimeters.
-     * 0 is the top-left when the user is facing the screen
-     * and the device orientation is Portrait.
-     */
-    private final int mLocationY;
-
-    public AvailableNfcAntenna(int locationX, int locationY) {
-        this.mLocationX = locationX;
-        this.mLocationY = locationY;
-    }
-
-    /**
-     * Location of the antenna on the X axis in millimeters.
-     * 0 is the top-left when the user is facing the screen
-     * and the device orientation is Portrait.
-     */
-    public int getLocationX() {
-        return mLocationX;
-    }
-
-    /**
-     * Location of the antenna on the Y axis in millimeters.
-     * 0 is the top-left when the user is facing the screen
-     * and the device orientation is Portrait.
-     */
-    public int getLocationY() {
-        return mLocationY;
-    }
-
-    private AvailableNfcAntenna(Parcel in) {
-        this.mLocationX = in.readInt();
-        this.mLocationY = in.readInt();
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<AvailableNfcAntenna>
-            CREATOR = new Parcelable.Creator<AvailableNfcAntenna>() {
-                @Override
-                public AvailableNfcAntenna createFromParcel(Parcel in) {
-                    return new AvailableNfcAntenna(in);
-                }
-
-                @Override
-                public AvailableNfcAntenna[] newArray(int size) {
-                    return new AvailableNfcAntenna[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mLocationX);
-        dest.writeInt(mLocationY);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + mLocationX;
-        result = prime * result + mLocationY;
-        return result;
-    }
-
-    /**
-     * Returns true if the specified AvailableNfcAntenna contains
-     * identical specifications.
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        AvailableNfcAntenna other = (AvailableNfcAntenna) obj;
-        if (this.mLocationX != other.mLocationX) return false;
-        return this.mLocationY == other.mLocationY;
-    }
-
-    @Override
-    public String toString() {
-        return "AvailableNfcAntenna " + "x: " + mLocationX + " y: " + mLocationY;
-    }
-}
diff --git a/nfc/java/android/nfc/ComponentNameAndUser.aidl b/nfc/java/android/nfc/ComponentNameAndUser.aidl
deleted file mode 100644
index e677998..0000000
--- a/nfc/java/android/nfc/ComponentNameAndUser.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable ComponentNameAndUser;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/ComponentNameAndUser.java b/nfc/java/android/nfc/ComponentNameAndUser.java
deleted file mode 100644
index 59e6c62..0000000
--- a/nfc/java/android/nfc/ComponentNameAndUser.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.UserIdInt;
-import android.content.ComponentName;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * @hide
- */
-public class ComponentNameAndUser implements Parcelable {
-    @UserIdInt private final int mUserId;
-    private ComponentName mComponentName;
-
-    public ComponentNameAndUser(@UserIdInt int userId, ComponentName componentName) {
-        mUserId = userId;
-        mComponentName = componentName;
-    }
-
-    /**
-     * @hide
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * @hide
-     */
-    public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mUserId);
-        out.writeParcelable(mComponentName, flags);
-    }
-
-    public static final Parcelable.Creator<ComponentNameAndUser> CREATOR =
-            new Parcelable.Creator<ComponentNameAndUser>() {
-                public ComponentNameAndUser createFromParcel(Parcel in) {
-                    return new ComponentNameAndUser(in);
-                }
-
-                public ComponentNameAndUser[] newArray(int size) {
-                    return new ComponentNameAndUser[size];
-                }
-            };
-
-    private ComponentNameAndUser(Parcel in) {
-        mUserId = in.readInt();
-        mComponentName = in.readParcelable(null, ComponentName.class);
-    }
-
-    @UserIdInt
-    public int getUserId() {
-        return mUserId;
-    }
-
-    public ComponentName getComponentName() {
-        return mComponentName;
-    }
-
-    @Override
-    public String toString() {
-        return mComponentName + " for user id: " + mUserId;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj != null && obj instanceof ComponentNameAndUser) {
-            ComponentNameAndUser other = (ComponentNameAndUser) obj;
-            return other.getUserId() == mUserId
-                    && Objects.equals(other.getComponentName(), mComponentName);
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        if (mComponentName == null) {
-            return mUserId;
-        }
-        return mComponentName.hashCode() + mUserId;
-    }
-}
diff --git a/nfc/java/android/nfc/Constants.java b/nfc/java/android/nfc/Constants.java
deleted file mode 100644
index 9b11e2d..0000000
--- a/nfc/java/android/nfc/Constants.java
+++ /dev/null
@@ -1,42 +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.nfc;
-
-import android.provider.Settings;
-
-/**
- * @hide
- * TODO(b/303286040): Holds @hide API constants. Formalize these APIs.
- */
-public final class Constants {
-    private Constants() { }
-
-    public static final String SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND = "nfc_payment_foreground";
-    public static final String SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
-    public static final String FEATURE_NFC_ANY = "android.hardware.nfc.any";
-
-    /**
-     * @hide constant copied from {@link Settings.Global}
-     * TODO(b/274636414): Migrate to official API in Android V.
-     */
-    public static final String SETTINGS_SATELLITE_MODE_RADIOS = "satellite_mode_radios";
-    /**
-     * @hide constant copied from {@link Settings.Global}
-     * TODO(b/274636414): Migrate to official API in Android V.
-     */
-    public static final String SETTINGS_SATELLITE_MODE_ENABLED = "satellite_mode_enabled";
-}
diff --git a/nfc/java/android/nfc/Entry.aidl b/nfc/java/android/nfc/Entry.aidl
deleted file mode 100644
index 148c4ec..0000000
--- a/nfc/java/android/nfc/Entry.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-parcelable Entry;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/Entry.java b/nfc/java/android/nfc/Entry.java
deleted file mode 100644
index aa5ba58..0000000
--- a/nfc/java/android/nfc/Entry.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-
-/** @hide */
-public final class Entry implements Parcelable {
-    private final byte mType;
-    private final byte mNfceeId;
-    private final String mEntry;
-    private final String mRoutingType;
-
-    public Entry(String entry, byte type, byte nfceeId, String routingType) {
-        mEntry = entry;
-        mType = type;
-        mNfceeId = nfceeId;
-        mRoutingType = routingType;
-    }
-
-    public byte getType() {
-        return mType;
-    }
-
-    public byte getNfceeId() {
-        return mNfceeId;
-    }
-
-    public String getEntry() {
-        return mEntry;
-    }
-
-    public String getRoutingType() {
-        return mRoutingType;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    private Entry(Parcel in) {
-        this.mEntry = in.readString();
-        this.mNfceeId = in.readByte();
-        this.mType = in.readByte();
-        this.mRoutingType = in.readString();
-    }
-
-    public static final @NonNull Parcelable.Creator<Entry> CREATOR =
-            new Parcelable.Creator<Entry>() {
-                @Override
-                public Entry createFromParcel(Parcel in) {
-                    return new Entry(in);
-                }
-
-                @Override
-                public Entry[] newArray(int size) {
-                    return new Entry[size];
-                }
-            };
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mEntry);
-        dest.writeByte(mNfceeId);
-        dest.writeByte(mType);
-        dest.writeString(mRoutingType);
-    }
-}
diff --git a/nfc/java/android/nfc/ErrorCodes.java b/nfc/java/android/nfc/ErrorCodes.java
deleted file mode 100644
index d2c81cd..0000000
--- a/nfc/java/android/nfc/ErrorCodes.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.compat.annotation.UnsupportedAppUsage;
-
-/**
- * This class defines all the error codes that can be returned by the service
- * and producing an exception on the application level. These are needed since
- * binders does not support exceptions.
- *
- * @hide
- */
-public class ErrorCodes {
-
-    @UnsupportedAppUsage
-    public static boolean isError(int code) {
-        if (code < 0) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    public static String asString(int code) {
-        switch (code) {
-            case SUCCESS: return "SUCCESS";
-            case ERROR_IO: return "IO";
-            case ERROR_CANCELLED: return "CANCELLED";
-            case ERROR_TIMEOUT: return "TIMEOUT";
-            case ERROR_BUSY: return "BUSY";
-            case ERROR_CONNECT: return "CONNECT/DISCONNECT";
-//            case ERROR_DISCONNECT: return "DISCONNECT";
-            case ERROR_READ: return "READ";
-            case ERROR_WRITE: return "WRITE";
-            case ERROR_INVALID_PARAM: return "INVALID_PARAM";
-            case ERROR_INSUFFICIENT_RESOURCES: return "INSUFFICIENT_RESOURCES";
-            case ERROR_SOCKET_CREATION: return "SOCKET_CREATION";
-            case ERROR_SOCKET_NOT_CONNECTED: return "SOCKET_NOT_CONNECTED";
-            case ERROR_BUFFER_TO_SMALL: return "BUFFER_TO_SMALL";
-            case ERROR_SAP_USED: return "SAP_USED";
-            case ERROR_SERVICE_NAME_USED: return "SERVICE_NAME_USED";
-            case ERROR_SOCKET_OPTIONS: return "SOCKET_OPTIONS";
-            case ERROR_NFC_ON: return "NFC_ON";
-            case ERROR_NOT_INITIALIZED: return "NOT_INITIALIZED";
-            case ERROR_SE_ALREADY_SELECTED: return "SE_ALREADY_SELECTED";
-            case ERROR_SE_CONNECTED: return "SE_CONNECTED";
-            case ERROR_NO_SE_CONNECTED: return "NO_SE_CONNECTED";
-            case ERROR_NOT_SUPPORTED: return "NOT_SUPPORTED";
-            default: return "UNKNOWN ERROR";
-        }
-    }
-
-    public static final int SUCCESS = 0;
-
-    public static final int ERROR_IO = -1;
-
-    public static final int ERROR_CANCELLED = -2;
-
-    public static final int ERROR_TIMEOUT = -3;
-
-    public static final int ERROR_BUSY = -4;
-
-    public static final int ERROR_CONNECT = -5;
-
-    public static final int ERROR_DISCONNECT = -5;
-
-    public static final int ERROR_READ = -6;
-
-    public static final int ERROR_WRITE = -7;
-
-    public static final int ERROR_INVALID_PARAM = -8;
-
-    public static final int ERROR_INSUFFICIENT_RESOURCES = -9;
-
-    public static final int ERROR_SOCKET_CREATION = -10;
-
-    public static final int ERROR_SOCKET_NOT_CONNECTED = -11;
-
-    public static final int ERROR_BUFFER_TO_SMALL = -12;
-
-    public static final int ERROR_SAP_USED = -13;
-
-    public static final int ERROR_SERVICE_NAME_USED = -14;
-
-    public static final int ERROR_SOCKET_OPTIONS = -15;
-
-    public static final int ERROR_NFC_ON = -16;
-
-    public static final int ERROR_NOT_INITIALIZED = -17;
-
-    public static final int ERROR_SE_ALREADY_SELECTED = -18;
-
-    public static final int ERROR_SE_CONNECTED = -19;
-
-    public static final int ERROR_NO_SE_CONNECTED = -20;
-
-    public static final int ERROR_NOT_SUPPORTED = -21;
-
-}
diff --git a/nfc/java/android/nfc/FormatException.java b/nfc/java/android/nfc/FormatException.java
deleted file mode 100644
index a57de1e..0000000
--- a/nfc/java/android/nfc/FormatException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-public class FormatException extends Exception {
-    public FormatException() {
-        super();
-    }
-
-    public FormatException(String message) {
-        super(message);
-    }
-
-    public FormatException(String message, Throwable e) {
-        super(message, e);
-    }
-}
diff --git a/nfc/java/android/nfc/IAppCallback.aidl b/nfc/java/android/nfc/IAppCallback.aidl
deleted file mode 100644
index b06bf06..0000000
--- a/nfc/java/android/nfc/IAppCallback.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.nfc.Tag;
-
-/**
- * @hide
- */
-interface IAppCallback
-{
-    oneway void onTagDiscovered(in Tag tag);
-}
diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl
deleted file mode 100644
index ac0a5aa..0000000
--- a/nfc/java/android/nfc/INfcAdapter.aidl
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.app.PendingIntent;
-import android.content.IntentFilter;
-import android.nfc.Entry;
-import android.nfc.NdefMessage;
-import android.nfc.Tag;
-import android.nfc.TechListParcel;
-import android.nfc.IAppCallback;
-import android.nfc.INfcAdapterExtras;
-import android.nfc.INfcControllerAlwaysOnListener;
-import android.nfc.INfcVendorNciCallback;
-import android.nfc.INfcTag;
-import android.nfc.INfcCardEmulation;
-import android.nfc.INfcFCardEmulation;
-import android.nfc.INfcOemExtensionCallback;
-import android.nfc.INfcUnlockHandler;
-import android.nfc.IT4tNdefNfcee;
-import android.nfc.ITagRemovedCallback;
-import android.nfc.INfcDta;
-import android.nfc.INfcWlcStateListener;
-import android.nfc.NfcAntennaInfo;
-import android.nfc.WlcListenerDeviceInfo;
-import android.nfc.cardemulation.PollingFrame;
-import android.os.Bundle;
-
-/**
- * @hide
- */
-interface INfcAdapter
-{
-    INfcTag getNfcTagInterface();
-    INfcCardEmulation getNfcCardEmulationInterface();
-    INfcFCardEmulation getNfcFCardEmulationInterface();
-    INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
-    INfcDta getNfcDtaInterface(in String pkg);
-    int getState();
-    boolean disable(boolean saveState, in String pkg);
-    boolean enable(in String pkg);
-    int pausePolling(long timeoutInMs);
-    int resumePolling();
-
-    void setForegroundDispatch(in PendingIntent intent,
-            in IntentFilter[] filters, in TechListParcel techLists);
-    void setAppCallback(in IAppCallback callback);
-
-    boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback);
-
-    void dispatch(in Tag tag);
-
-    void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras, String pkg);
-
-    void addNfcUnlockHandler(INfcUnlockHandler unlockHandler, in int[] techList);
-    void removeNfcUnlockHandler(INfcUnlockHandler unlockHandler);
-
-    void verifyNfcPermission();
-    boolean isNfcSecureEnabled();
-    boolean deviceSupportsNfcSecure();
-    boolean setNfcSecure(boolean enable);
-    NfcAntennaInfo getNfcAntennaInfo();
-
-    void setControllerAlwaysOn(int mode);
-    boolean isControllerAlwaysOn();
-    boolean isControllerAlwaysOnSupported();
-    void registerControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
-    void unregisterControllerAlwaysOnListener(in INfcControllerAlwaysOnListener listener);
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    boolean isTagIntentAppPreferenceSupported();
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    Map getTagIntentAppPreferenceForUser(int userId);
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    int setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow);
-
-    boolean isReaderOptionEnabled();
-    boolean isReaderOptionSupported();
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    boolean enableReaderOption(boolean enable, in String pkg);
-    boolean isObserveModeSupported();
-    boolean isObserveModeEnabled();
-    boolean setObserveMode(boolean enabled, String pkg);
-
-    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
-    boolean setWlcEnabled(boolean enable);
-    boolean isWlcEnabled();
-    void registerWlcStateListener(in INfcWlcStateListener listener);
-    void unregisterWlcStateListener(in INfcWlcStateListener listener);
-    WlcListenerDeviceInfo getWlcListenerDeviceInfo();
-
-    void updateDiscoveryTechnology(IBinder b, int pollFlags, int listenFlags, String pkg);
-
-    void notifyPollingLoop(in PollingFrame frame);
-    void notifyHceDeactivated();
-    void notifyTestHceData(in int technology, in byte[] data);
-    int sendVendorNciMessage(int mt, int gid, int oid, in byte[] payload);
-    void registerVendorExtensionCallback(in INfcVendorNciCallback callbacks);
-    void unregisterVendorExtensionCallback(in INfcVendorNciCallback callbacks);
-    void registerOemExtensionCallback(INfcOemExtensionCallback callbacks);
-    void unregisterOemExtensionCallback(INfcOemExtensionCallback callbacks);
-    void clearPreference();
-    void setScreenState();
-    void checkFirmware();
-    Map fetchActiveNfceeList();
-    void triggerInitialization();
-    boolean getSettingStatus();
-    boolean isTagPresent();
-    List<Entry> getRoutingTableEntryList();
-    void indicateDataMigration(boolean inProgress, String pkg);
-    int commitRouting();
-    boolean isTagIntentAllowed(in String pkg, in int Userid);
-    IT4tNdefNfcee getT4tNdefNfceeInterface();
-    long getMaxPausePollingTimeoutMs();
-}
diff --git a/nfc/java/android/nfc/INfcAdapterExtras.aidl b/nfc/java/android/nfc/INfcAdapterExtras.aidl
deleted file mode 100644
index cde57c5..0000000
--- a/nfc/java/android/nfc/INfcAdapterExtras.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.os.Bundle;
-
-
-/**
- * {@hide}
- */
-interface INfcAdapterExtras {
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    Bundle open(in String pkg, IBinder b);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    Bundle close(in String pkg, IBinder b);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    Bundle transceive(in String pkg, in byte[] data_in);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    int getCardEmulationRoute(in String pkg);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    void setCardEmulationRoute(in String pkg, int route);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    void authenticate(in String pkg, in byte[] token);
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    String getDriverName(in String pkg);
-}
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
deleted file mode 100644
index 00ceaa9..0000000
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.content.ComponentName;
-import android.nfc.INfcEventCallback;
-
-import android.nfc.cardemulation.AidGroup;
-import android.nfc.cardemulation.ApduServiceInfo;
-import android.os.RemoteCallback;
-
-/**
- * @hide
- */
-interface INfcCardEmulation
-{
-    boolean isDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
-    boolean isDefaultServiceForAid(int userHandle, in ComponentName service, String aid);
-    boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
-    boolean setDefaultForNextTap(int userHandle, in ComponentName service);
-    boolean setShouldDefaultToObserveModeForService(int userId, in android.content.ComponentName service, boolean enable);
-    boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup);
-    boolean registerPollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter, boolean autoTransact);
-    boolean registerPollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter, boolean autoTransact);
-    boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement);
-    boolean unsetOffHostForService(int userHandle, in ComponentName service);
-    AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
-    boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
-    boolean removePollingLoopFilterForService(int userHandle, in ComponentName service, in String pollingLoopFilter);
-    boolean removePollingLoopPatternFilterForService(int userHandle, in ComponentName service, in String pollingLoopPatternFilter);
-    List<ApduServiceInfo> getServices(int userHandle, in String category);
-    boolean setPreferredService(in ComponentName service);
-    boolean unsetPreferredService();
-    boolean supportsAidPrefixRegistration();
-    ApduServiceInfo getPreferredPaymentService(int userHandle);
-    int setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
-    boolean isDefaultPaymentRegistered();
-
-    void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
-    void recoverRoutingTable(int userHandle);
-    boolean isEuiccSupported();
-    int getDefaultNfcSubscriptionId(in String pkg);
-    int setDefaultNfcSubscriptionId(int subscriptionId, in String pkg);
-    void setAutoChangeStatus(boolean state);
-    boolean isAutoChangeEnabled();
-    List<String> getRoutingStatus();
-    void overwriteRoutingTable(int userHandle, String emptyAid, String protocol, String tech, String sc);
-
-    void registerNfcEventCallback(in INfcEventCallback listener);
-    void unregisterNfcEventCallback(in INfcEventCallback listener);
-}
diff --git a/nfc/java/android/nfc/INfcControllerAlwaysOnListener.aidl b/nfc/java/android/nfc/INfcControllerAlwaysOnListener.aidl
deleted file mode 100644
index 1bb7680..0000000
--- a/nfc/java/android/nfc/INfcControllerAlwaysOnListener.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-/**
- * @hide
- */
-oneway interface INfcControllerAlwaysOnListener {
-  /**
-   * Called whenever the controller always on state changes
-   *
-   * @param isEnabled true if the state is enabled, false otherwise
-   */
-  void onControllerAlwaysOnChanged(boolean isEnabled);
-}
diff --git a/nfc/java/android/nfc/INfcDta.aidl b/nfc/java/android/nfc/INfcDta.aidl
deleted file mode 100644
index 4cc5927..0000000
--- a/nfc/java/android/nfc/INfcDta.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
- /*
-  * Copyright (C) 2017 NXP Semiconductors
-  *
-  * Licensed under the Apache License, Version 2.0 (the "License");
-  * you may not use this file except in compliance with the License.
-  * You may obtain a copy of the License at
-  *
-  *      http://www.apache.org/licenses/LICENSE-2.0
-  *
-  * Unless required by applicable law or agreed to in writing, software
-  * distributed under the License is distributed on an "AS IS" BASIS,
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  * See the License for the specific language governing permissions and
-  * limitations under the License.
-  */
-package android.nfc;
-
-import android.os.Bundle;
-
-/**
- * {@hide}
- */
-interface INfcDta {
-
-    void enableDta();
-    void disableDta();
-    boolean enableServer(String serviceName, int serviceSap, int miu,
-            int rwSize,int testCaseId);
-    void disableServer();
-    boolean enableClient(String serviceName, int miu, int rwSize,
-            int testCaseId);
-    void disableClient();
-    boolean registerMessageService(String msgServiceName);
-}
diff --git a/nfc/java/android/nfc/INfcEventCallback.aidl b/nfc/java/android/nfc/INfcEventCallback.aidl
deleted file mode 100644
index af1fa2fb..0000000
--- a/nfc/java/android/nfc/INfcEventCallback.aidl
+++ /dev/null
@@ -1,16 +0,0 @@
-package android.nfc;
-
-import android.nfc.ComponentNameAndUser;
-
-/**
- * @hide
- */
-oneway interface INfcEventCallback {
-    void onPreferredServiceChanged(in ComponentNameAndUser ComponentNameAndUser);
-    void onObserveModeStateChanged(boolean isEnabled);
-    void onAidConflictOccurred(in String aid);
-    void onAidNotRouted(in String aid);
-    void onNfcStateChanged(in int nfcState);
-    void onRemoteFieldChanged(boolean isDetected);
-    void onInternalErrorReported(in int errorType);
-}
\ No newline at end of file
diff --git a/nfc/java/android/nfc/INfcFCardEmulation.aidl b/nfc/java/android/nfc/INfcFCardEmulation.aidl
deleted file mode 100644
index 124bfac..0000000
--- a/nfc/java/android/nfc/INfcFCardEmulation.aidl
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.content.ComponentName;
-import android.nfc.cardemulation.NfcFServiceInfo;
-
-/**
- * @hide
- */
-interface INfcFCardEmulation
-{
-    String getSystemCodeForService(int userHandle, in ComponentName service);
-    boolean registerSystemCodeForService(int userHandle, in ComponentName service, String systemCode);
-    boolean removeSystemCodeForService(int userHandle, in ComponentName service);
-    String getNfcid2ForService(int userHandle, in ComponentName service);
-    boolean setNfcid2ForService(int userHandle, in ComponentName service, String nfcid2);
-    boolean enableNfcFForegroundService(in ComponentName service);
-    boolean disableNfcFForegroundService();
-    List<NfcFServiceInfo> getNfcFServices(int userHandle);
-    int getMaxNumOfRegisterableSystemCodes();
-}
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
deleted file mode 100644
index e5eac0b..0000000
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.content.ComponentName;
-import android.nfc.cardemulation.ApduServiceInfo;
-import android.nfc.NdefMessage;
-import android.nfc.OemLogItems;
-import android.nfc.Tag;
-import android.os.ResultReceiver;
-
-import java.util.List;
-
-/**
- * @hide
- */
-interface INfcOemExtensionCallback {
-   void onTagConnected(boolean connected);
-   void onStateUpdated(int state);
-   void onApplyRouting(in ResultReceiver isSkipped);
-   void onNdefRead(in ResultReceiver isSkipped);
-   void onEnable(in ResultReceiver isAllowed);
-   void onDisable(in ResultReceiver isAllowed);
-   void onBootStarted();
-   void onEnableStarted();
-   void onDisableStarted();
-   void onBootFinished(int status);
-   void onEnableFinished(int status);
-   void onDisableFinished(int status);
-   void onTagDispatch(in ResultReceiver isSkipped);
-   void onRoutingChanged(in ResultReceiver isSkipped);
-   void onHceEventReceived(int action);
-   void onReaderOptionChanged(boolean enabled);
-   void onCardEmulationActivated(boolean isActivated);
-   void onRfFieldActivated(boolean isActivated);
-   void onRfDiscoveryStarted(boolean isDiscoveryStarted);
-   void onEeListenActivated(boolean isActivated);
-   void onEeUpdated();
-   void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer);
-   void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent);
-   void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category);
-   void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category);
-   void onRoutingTableFull();
-   void onLogEventNotified(in OemLogItems item);
-   void onExtractOemPackages(in NdefMessage message, in ResultReceiver packageReceiver);
-}
diff --git a/nfc/java/android/nfc/INfcTag.aidl b/nfc/java/android/nfc/INfcTag.aidl
deleted file mode 100644
index 170df71..0000000
--- a/nfc/java/android/nfc/INfcTag.aidl
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.nfc.NdefMessage;
-import android.nfc.Tag;
-import android.nfc.TransceiveResult;
-
-/**
- * @hide
- */
-interface INfcTag
-{
-    int connect(int nativeHandle, int technology);
-    int reconnect(int nativeHandle);
-    int[] getTechList(int nativeHandle);
-    boolean isNdef(int nativeHandle);
-    boolean isPresent(int nativeHandle);
-    TransceiveResult transceive(int nativeHandle, in byte[] data, boolean raw);
-
-    NdefMessage ndefRead(int nativeHandle);
-    int ndefWrite(int nativeHandle, in NdefMessage msg);
-    int ndefMakeReadOnly(int nativeHandle);
-    boolean ndefIsWritable(int nativeHandle);
-    int formatNdef(int nativeHandle, in byte[] key);
-    Tag rediscover(int nativehandle);
-
-    int setTimeout(int technology, int timeout);
-    int getTimeout(int technology);
-    void resetTimeouts();
-    boolean canMakeReadOnly(int ndefType);
-    int getMaxTransceiveLength(int technology);
-    boolean getExtendedLengthApdusSupported();
-
-    boolean isTagUpToDate(long cookie);
-}
diff --git a/nfc/java/android/nfc/INfcUnlockHandler.aidl b/nfc/java/android/nfc/INfcUnlockHandler.aidl
deleted file mode 100644
index e1cace9..0000000
--- a/nfc/java/android/nfc/INfcUnlockHandler.aidl
+++ /dev/null
@@ -1,12 +0,0 @@
-package android.nfc;
-
-import android.nfc.Tag;
-
-/**
- * @hide
- */
-interface INfcUnlockHandler {
-
-    boolean onUnlockAttempted(in Tag tag);
-
-}
diff --git a/nfc/java/android/nfc/INfcWlcStateListener.aidl b/nfc/java/android/nfc/INfcWlcStateListener.aidl
deleted file mode 100644
index 584eb9a..0000000
--- a/nfc/java/android/nfc/INfcWlcStateListener.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.nfc.WlcListenerDeviceInfo;
-/**
- * @hide
- */
-oneway interface INfcWlcStateListener {
-  /**
-   * Called whenever NFC WLC state changes
-   *
-   * @param wlcListenerDeviceInfo NFC wlc listener information
-   */
-  void onWlcStateChanged(in WlcListenerDeviceInfo wlcListenerDeviceInfo);
-}
diff --git a/nfc/java/android/nfc/IT4tNdefNfcee.aidl b/nfc/java/android/nfc/IT4tNdefNfcee.aidl
deleted file mode 100644
index b4cda5b..0000000
--- a/nfc/java/android/nfc/IT4tNdefNfcee.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2024 The Android Open Source Project.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-package android.nfc;
-
-import android.nfc.T4tNdefNfceeCcFileInfo;
-
-/**
- * @hide
- */
-interface IT4tNdefNfcee {
-    int writeData(in int fileId, in byte[] data);
-    byte[] readData(in int fileId);
-    int clearNdefData();
-    boolean isNdefOperationOngoing();
-    boolean isNdefNfceeEmulationSupported();
-    T4tNdefNfceeCcFileInfo readCcfile();
-}
diff --git a/nfc/java/android/nfc/ITagRemovedCallback.aidl b/nfc/java/android/nfc/ITagRemovedCallback.aidl
deleted file mode 100644
index 2a06ff3..0000000
--- a/nfc/java/android/nfc/ITagRemovedCallback.aidl
+++ /dev/null
@@ -1,8 +0,0 @@
-package android.nfc;
-
-/**
- * @hide
- */
-oneway interface ITagRemovedCallback {
-    void onTagRemoved();
-}
diff --git a/nfc/java/android/nfc/NdefMessage.aidl b/nfc/java/android/nfc/NdefMessage.aidl
deleted file mode 100644
index 378b9d0..0000000
--- a/nfc/java/android/nfc/NdefMessage.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable NdefMessage;
diff --git a/nfc/java/android/nfc/NdefMessage.java b/nfc/java/android/nfc/NdefMessage.java
deleted file mode 100644
index 553f6c0..0000000
--- a/nfc/java/android/nfc/NdefMessage.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.proto.ProtoOutputStream;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-/**
- * Represents an immutable NDEF Message.
- * <p>
- * NDEF (NFC Data Exchange Format) is a light-weight binary format,
- * used to encapsulate typed data. It is specified by the NFC Forum,
- * for transmission and storage with NFC, however it is transport agnostic.
- * <p>
- * NDEF defines messages and records. An NDEF Record contains
- * typed data, such as MIME-type media, a URI, or a custom
- * application payload. An NDEF Message is a container for
- * one or more NDEF Records.
- * <p>
- * When an Android device receives an NDEF Message
- * (for example by reading an NFC tag) it processes it through
- * a dispatch mechanism to determine an activity to launch.
- * The type of the <em>first</em> record in the message has
- * special importance for message dispatch, so design this record
- * carefully.
- * <p>
- * Use {@link #NdefMessage(byte[])} to construct an NDEF Message from
- * binary data, or {@link #NdefMessage(NdefRecord[])} to
- * construct from one or more {@link NdefRecord}s.
- * <p class="note">
- * {@link NdefMessage} and {@link NdefRecord} implementations are
- * always available, even on Android devices that do not have NFC hardware.
- * <p class="note">
- * {@link NdefRecord}s are intended to be immutable (and thread-safe),
- * however they may contain mutable fields. So take care not to modify
- * mutable fields passed into constructors, or modify mutable fields
- * obtained by getter methods, unless such modification is explicitly
- * marked as safe.
- *
- * @see NfcAdapter#ACTION_NDEF_DISCOVERED
- * @see NdefRecord
- */
-public final class NdefMessage implements Parcelable {
-    private final NdefRecord[] mRecords;
-
-    /**
-     * Construct an NDEF Message by parsing raw bytes.<p>
-     * Strict validation of the NDEF binary structure is performed:
-     * there must be at least one record, every record flag must
-     * be correct, and the total length of the message must match
-     * the length of the input data.<p>
-     * This parser can handle chunked records, and converts them
-     * into logical {@link NdefRecord}s within the message.<p>
-     * Once the input data has been parsed to one or more logical
-     * records, basic validation of the tnf, type, id, and payload fields
-     * of each record is performed, as per the documentation on
-     * on {@link NdefRecord#NdefRecord(short, byte[], byte[], byte[])}<p>
-     * If either strict validation of the binary format fails, or
-     * basic validation during record construction fails, a
-     * {@link FormatException} is thrown<p>
-     * Deep inspection of the type, id and payload fields of
-     * each record is not performed, so it is possible to parse input
-     * that has a valid binary format and confirms to the basic
-     * validation requirements of
-     * {@link NdefRecord#NdefRecord(short, byte[], byte[], byte[])},
-     * but fails more strict requirements as specified by the
-     * NFC Forum.
-     *
-     * <p class="note">
-     * It is safe to re-use the data byte array after construction:
-     * this constructor will make an internal copy of all necessary fields.
-     *
-     * @param data raw bytes to parse
-     * @throws FormatException if the data cannot be parsed
-     */
-    public NdefMessage(byte[] data) throws FormatException {
-        if (data == null) throw new NullPointerException("data is null");
-        ByteBuffer buffer = ByteBuffer.wrap(data);
-
-        mRecords = NdefRecord.parse(buffer, false);
-
-        if (buffer.remaining() > 0) {
-            throw new FormatException("trailing data");
-        }
-    }
-
-    /**
-     * Construct an NDEF Message from one or more NDEF Records.
-     *
-     * @param record first record (mandatory)
-     * @param records additional records (optional)
-     */
-    public NdefMessage(NdefRecord record, NdefRecord ... records) {
-        // validate
-        if (record == null) throw new NullPointerException("record cannot be null");
-
-        for (NdefRecord r : records) {
-            if (r == null) {
-                throw new NullPointerException("record cannot be null");
-            }
-        }
-
-        mRecords = new NdefRecord[1 + records.length];
-        mRecords[0] = record;
-        System.arraycopy(records, 0, mRecords, 1, records.length);
-    }
-
-    /**
-     * Construct an NDEF Message from one or more NDEF Records.
-     *
-     * @param records one or more records
-     */
-    public NdefMessage(NdefRecord[] records) {
-        // validate
-        if (records.length < 1) {
-            throw new IllegalArgumentException("must have at least one record");
-        }
-        for (NdefRecord r : records) {
-            if (r == null) {
-                throw new NullPointerException("records cannot contain null");
-            }
-        }
-
-        mRecords = records;
-    }
-
-    /**
-     * Get the NDEF Records inside this NDEF Message.<p>
-     * An {@link NdefMessage} always has one or more NDEF Records: so the
-     * following code to retrieve the first record is always safe
-     * (no need to check for null or array length >= 1):
-     * <pre>
-     * NdefRecord firstRecord = ndefMessage.getRecords()[0];
-     * </pre>
-     *
-     * @return array of one or more NDEF records.
-     */
-    public NdefRecord[] getRecords() {
-        return mRecords;
-    }
-
-    /**
-     * Return the length of this NDEF Message if it is written to a byte array
-     * with {@link #toByteArray}.<p>
-     * An NDEF Message can be formatted to bytes in different ways
-     * depending on chunking, SR, and ID flags, so the length returned
-     * by this method may not be equal to the length of the original
-     * byte array used to construct this NDEF Message. However it will
-     * always be equal to the length of the byte array produced by
-     * {@link #toByteArray}.
-     *
-     * @return length of this NDEF Message when written to bytes with {@link #toByteArray}
-     * @see #toByteArray
-     */
-    public int getByteArrayLength() {
-        int length = 0;
-        for (NdefRecord r : mRecords) {
-            length += r.getByteLength();
-        }
-        return length;
-    }
-
-    /**
-     * Return this NDEF Message as raw bytes.<p>
-     * The NDEF Message is formatted as per the NDEF 1.0 specification,
-     * and the byte array is suitable for network transmission or storage
-     * in an NFC Forum NDEF compatible tag.<p>
-     * This method will not chunk any records, and will always use the
-     * short record (SR) format and omit the identifier field when possible.
-     *
-     * @return NDEF Message in binary format
-     * @see #getByteArrayLength()
-     */
-    public byte[] toByteArray() {
-        int length = getByteArrayLength();
-        ByteBuffer buffer = ByteBuffer.allocate(length);
-
-        for (int i=0; i<mRecords.length; i++) {
-            boolean mb = (i == 0);  // first record
-            boolean me = (i == mRecords.length - 1);  // last record
-            mRecords[i].writeToByteBuffer(buffer, mb, me);
-        }
-
-        return buffer.array();
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mRecords.length);
-        dest.writeTypedArray(mRecords, flags);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<NdefMessage> CREATOR =
-            new Parcelable.Creator<NdefMessage>() {
-        @Override
-        public NdefMessage createFromParcel(Parcel in) {
-            int recordsLength = in.readInt();
-            NdefRecord[] records = new NdefRecord[recordsLength];
-            in.readTypedArray(records, NdefRecord.CREATOR);
-            return new NdefMessage(records);
-        }
-        @Override
-        public NdefMessage[] newArray(int size) {
-            return new NdefMessage[size];
-        }
-    };
-
-    @Override
-    public int hashCode() {
-        return Arrays.hashCode(mRecords);
-    }
-
-    /**
-     * Returns true if the specified NDEF Message contains
-     * identical NDEF Records.
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        NdefMessage other = (NdefMessage) obj;
-        return Arrays.equals(mRecords, other.mRecords);
-    }
-
-    @Override
-    public String toString() {
-        return "NdefMessage " + Arrays.toString(mRecords);
-    }
-
-    /**
-     * Dump debugging information as a NdefMessageProto
-     * @hide
-     *
-     * Note:
-     * See proto definition in frameworks/base/core/proto/android/nfc/ndef.proto
-     * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
-     * {@link ProtoOutputStream#end(long)} after.
-     * Never reuse a proto field number. When removing a field, mark it as reserved.
-     */
-    public void dumpDebug(ProtoOutputStream proto) {
-        for (NdefRecord record : mRecords) {
-            long token = proto.start(NdefMessageProto.NDEF_RECORDS);
-            record.dumpDebug(proto);
-            proto.end(token);
-        }
-    }
-}
\ No newline at end of file
diff --git a/nfc/java/android/nfc/NdefRecord.aidl b/nfc/java/android/nfc/NdefRecord.aidl
deleted file mode 100644
index 10f89d0..0000000
--- a/nfc/java/android/nfc/NdefRecord.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable NdefRecord;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/NdefRecord.java b/nfc/java/android/nfc/NdefRecord.java
deleted file mode 100644
index 7bf4355..0000000
--- a/nfc/java/android/nfc/NdefRecord.java
+++ /dev/null
@@ -1,1080 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.proto.ProtoOutputStream;
-
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Represents an immutable NDEF Record.
- * <p>
- * NDEF (NFC Data Exchange Format) is a light-weight binary format,
- * used to encapsulate typed data. It is specified by the NFC Forum,
- * for transmission and storage with NFC, however it is transport agnostic.
- * <p>
- * NDEF defines messages and records. An NDEF Record contains
- * typed data, such as MIME-type media, a URI, or a custom
- * application payload. An NDEF Message is a container for
- * one or more NDEF Records.
- * <p>
- * This class represents logical (complete) NDEF Records, and can not be
- * used to represent chunked (partial) NDEF Records. However
- * {@link NdefMessage#NdefMessage(byte[])} can be used to parse a message
- * containing chunked records, and will return a message with unchunked
- * (complete) records.
- * <p>
- * A logical NDEF Record always contains a 3-bit TNF (Type Name Field)
- * that provides high level typing for the rest of the record. The
- * remaining fields are variable length and not always present:
- * <ul>
- * <li><em>type</em>: detailed typing for the payload</li>
- * <li><em>id</em>: identifier meta-data, not commonly used</li>
- * <li><em>payload</em>: the actual payload</li>
- * </ul>
- * <p>
- * Helpers such as {@link NdefRecord#createUri}, {@link NdefRecord#createMime}
- * and {@link NdefRecord#createExternal} are included to create well-formatted
- * NDEF Records with correctly set tnf, type, id and payload fields, please
- * use these helpers whenever possible.
- * <p>
- * Use the constructor {@link #NdefRecord(short, byte[], byte[], byte[])}
- * if you know what you are doing and what to set the fields individually.
- * Only basic validation is performed with this constructor, so it is possible
- * to create records that do not confirm to the strict NFC Forum
- * specifications.
- * <p>
- * The binary representation of an NDEF Record includes additional flags to
- * indicate location with an NDEF message, provide support for chunking of
- * NDEF records, and to pack optional fields. This class does not expose
- * those details. To write an NDEF Record as binary you must first put it
- * into an {@link NdefMessage}, then call {@link NdefMessage#toByteArray()}.
- * <p class="note">
- * {@link NdefMessage} and {@link NdefRecord} implementations are
- * always available, even on Android devices that do not have NFC hardware.
- * <p class="note">
- * {@link NdefRecord}s are intended to be immutable (and thread-safe),
- * however they may contain mutable fields. So take care not to modify
- * mutable fields passed into constructors, or modify mutable fields
- * obtained by getter methods, unless such modification is explicitly
- * marked as safe.
- *
- * @see NfcAdapter#ACTION_NDEF_DISCOVERED
- * @see NdefMessage
- */
-public final class NdefRecord implements Parcelable {
-    /**
-     * Indicates the record is empty.<p>
-     * Type, id and payload fields are empty in a {@literal TNF_EMPTY} record.
-     */
-    public static final short TNF_EMPTY = 0x00;
-
-    /**
-     * Indicates the type field contains a well-known RTD type name.<p>
-     * Use this tnf with RTD types such as {@link #RTD_TEXT}, {@link #RTD_URI}.
-     * <p>
-     * The RTD type name format is specified in NFCForum-TS-RTD_1.0.
-     *
-     * @see #RTD_URI
-     * @see #RTD_TEXT
-     * @see #RTD_SMART_POSTER
-     * @see #createUri
-     */
-    public static final short TNF_WELL_KNOWN = 0x01;
-
-    /**
-     * Indicates the type field contains a media-type BNF
-     * construct, defined by RFC 2046.<p>
-     * Use this with MIME type names such as {@literal "image/jpeg"}, or
-     * using the helper {@link #createMime}.
-     *
-     * @see #createMime
-     */
-    public static final short TNF_MIME_MEDIA = 0x02;
-
-    /**
-     * Indicates the type field contains an absolute-URI
-     * BNF construct defined by RFC 3986.<p>
-     * When creating new records prefer {@link #createUri},
-     * since it offers more compact URI encoding
-     * ({@literal #RTD_URI} allows compression of common URI prefixes).
-     *
-     * @see #createUri
-     */
-    public static final short TNF_ABSOLUTE_URI = 0x03;
-
-    /**
-     * Indicates the type field contains an external type name.<p>
-     * Used to encode custom payloads. When creating new records
-     * use the helper {@link #createExternal}.<p>
-     * The external-type RTD format is specified in NFCForum-TS-RTD_1.0.<p>
-     * <p>
-     * Note this TNF should not be used with RTD_TEXT or RTD_URI constants.
-     * Those are well known RTD constants, not external RTD constants.
-     *
-     * @see #createExternal
-     */
-    public static final short TNF_EXTERNAL_TYPE = 0x04;
-
-    /**
-     * Indicates the payload type is unknown.<p>
-     * NFC Forum explains this should be treated similarly to the
-     * "application/octet-stream" MIME type. The payload
-     * type is not explicitly encoded within the record.
-     * <p>
-     * The type field is empty in an {@literal TNF_UNKNOWN} record.
-     */
-    public static final short TNF_UNKNOWN = 0x05;
-
-    /**
-     * Indicates the payload is an intermediate or final chunk of a chunked
-     * NDEF Record.<p>
-     * {@literal TNF_UNCHANGED} can not be used with this class
-     * since all {@link NdefRecord}s are already unchunked, however they
-     * may appear in the binary format.
-     */
-    public static final short TNF_UNCHANGED = 0x06;
-
-    /**
-     * Reserved TNF type.
-     * <p>
-     * The NFC Forum NDEF Specification v1.0 suggests for NDEF parsers to treat this
-     * value like TNF_UNKNOWN.
-     * @hide
-     */
-    public static final short TNF_RESERVED = 0x07;
-
-    /**
-     * RTD Text type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_TEXT = {0x54};  // "T"
-
-    /**
-     * RTD URI type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_URI = {0x55};   // "U"
-
-    /**
-     * RTD Smart Poster type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_SMART_POSTER = {0x53, 0x70};  // "Sp"
-
-    /**
-     * RTD Alternative Carrier type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_ALTERNATIVE_CARRIER = {0x61, 0x63};  // "ac"
-
-    /**
-     * RTD Handover Carrier type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_HANDOVER_CARRIER = {0x48, 0x63};  // "Hc"
-
-    /**
-     * RTD Handover Request type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_HANDOVER_REQUEST = {0x48, 0x72};  // "Hr"
-
-    /**
-     * RTD Handover Select type. For use with {@literal TNF_WELL_KNOWN}.
-     * @see #TNF_WELL_KNOWN
-     */
-    public static final byte[] RTD_HANDOVER_SELECT = {0x48, 0x73}; // "Hs"
-
-    /**
-     * RTD Android app type. For use with {@literal TNF_EXTERNAL}.
-     * <p>
-     * The payload of a record with type RTD_ANDROID_APP
-     * should be the package name identifying an application.
-     * Multiple RTD_ANDROID_APP records may be included
-     * in a single {@link NdefMessage}.
-     * <p>
-     * Use {@link #createApplicationRecord(String)} to create
-     * RTD_ANDROID_APP records.
-     * @hide
-     */
-    public static final byte[] RTD_ANDROID_APP = "android.com:pkg".getBytes();
-
-    private static final byte FLAG_MB = (byte) 0x80;
-    private static final byte FLAG_ME = (byte) 0x40;
-    private static final byte FLAG_CF = (byte) 0x20;
-    private static final byte FLAG_SR = (byte) 0x10;
-    private static final byte FLAG_IL = (byte) 0x08;
-
-    /**
-     * NFC Forum "URI Record Type Definition"<p>
-     * This is a mapping of "URI Identifier Codes" to URI string prefixes,
-     * per section 3.2.2 of the NFC Forum URI Record Type Definition document.
-     */
-    private static final String[] URI_PREFIX_MAP = new String[] {
-            "", // 0x00
-            "http://www.", // 0x01
-            "https://www.", // 0x02
-            "http://", // 0x03
-            "https://", // 0x04
-            "tel:", // 0x05
-            "mailto:", // 0x06
-            "ftp://anonymous:anonymous@", // 0x07
-            "ftp://ftp.", // 0x08
-            "ftps://", // 0x09
-            "sftp://", // 0x0A
-            "smb://", // 0x0B
-            "nfs://", // 0x0C
-            "ftp://", // 0x0D
-            "dav://", // 0x0E
-            "news:", // 0x0F
-            "telnet://", // 0x10
-            "imap:", // 0x11
-            "rtsp://", // 0x12
-            "urn:", // 0x13
-            "pop:", // 0x14
-            "sip:", // 0x15
-            "sips:", // 0x16
-            "tftp:", // 0x17
-            "btspp://", // 0x18
-            "btl2cap://", // 0x19
-            "btgoep://", // 0x1A
-            "tcpobex://", // 0x1B
-            "irdaobex://", // 0x1C
-            "file://", // 0x1D
-            "urn:epc:id:", // 0x1E
-            "urn:epc:tag:", // 0x1F
-            "urn:epc:pat:", // 0x20
-            "urn:epc:raw:", // 0x21
-            "urn:epc:", // 0x22
-            "urn:nfc:", // 0x23
-    };
-
-    private static final int MAX_PAYLOAD_SIZE = 10 * (1 << 20);  // 10 MB payload limit
-
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-
-    private final short mTnf;
-    private final byte[] mType;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    private final byte[] mId;
-    private final byte[] mPayload;
-
-    /**
-     * Create a new Android Application Record (AAR).
-     * <p>
-     * This record indicates to other Android devices the package
-     * that should be used to handle the entire NDEF message.
-     * You can embed this record anywhere into your message
-     * to ensure that the intended package receives the message.
-     * <p>
-     * When an Android device dispatches an {@link NdefMessage}
-     * containing one or more Android application records,
-     * the applications contained in those records will be the
-     * preferred target for the {@link NfcAdapter#ACTION_NDEF_DISCOVERED}
-     * intent, in the order in which they appear in the message.
-     * This dispatch behavior was first added to Android in
-     * Ice Cream Sandwich.
-     * <p>
-     * If none of the applications have a are installed on the device,
-     * a Market link will be opened to the first application.
-     * <p>
-     * Note that Android application records do not overrule
-     * applications that have called
-     * {@link NfcAdapter#enableForegroundDispatch}.
-     *
-     * @param packageName Android package name
-     * @return Android application NDEF record
-     */
-    public static NdefRecord createApplicationRecord(String packageName) {
-        if (packageName == null) throw new NullPointerException("packageName is null");
-        if (packageName.length() == 0) throw new IllegalArgumentException("packageName is empty");
-
-        return new NdefRecord(TNF_EXTERNAL_TYPE, RTD_ANDROID_APP, null,
-                packageName.getBytes(StandardCharsets.UTF_8));
-    }
-
-    /**
-     * Create a new NDEF Record containing a URI.<p>
-     * Use this method to encode a URI (or URL) into an NDEF Record.<p>
-     * Uses the well known URI type representation: {@link #TNF_WELL_KNOWN}
-     * and {@link #RTD_URI}. This is the most efficient encoding
-     * of a URI into NDEF.<p>
-     * The uri parameter will be normalized with
-     * {@link Uri#normalizeScheme} to set the scheme to lower case to
-     * follow Android best practices for intent filtering.
-     * However the unchecked exception
-     * {@link IllegalArgumentException} may be thrown if the uri
-     * parameter has serious problems, for example if it is empty, so always
-     * catch this exception if you are passing user-generated data into this
-     * method.<p>
-     *
-     * Reference specification: NFCForum-TS-RTD_URI_1.0
-     *
-     * @param uri URI to encode.
-     * @return an NDEF Record containing the URI
-     * @throws IllegalArugmentException if the uri is empty or invalid
-     */
-    public static NdefRecord createUri(Uri uri) {
-        if (uri == null) throw new NullPointerException("uri is null");
-
-        uri = uri.normalizeScheme();
-        String uriString = uri.toString();
-        if (uriString.length() == 0) throw new IllegalArgumentException("uri is empty");
-
-        byte prefix = 0;
-        for (int i = 1; i < URI_PREFIX_MAP.length; i++) {
-            if (uriString.startsWith(URI_PREFIX_MAP[i])) {
-                prefix = (byte) i;
-                uriString = uriString.substring(URI_PREFIX_MAP[i].length());
-                break;
-            }
-        }
-        byte[] uriBytes = uriString.getBytes(StandardCharsets.UTF_8);
-        byte[] recordBytes = new byte[uriBytes.length + 1];
-        recordBytes[0] = prefix;
-        System.arraycopy(uriBytes, 0, recordBytes, 1, uriBytes.length);
-        return new NdefRecord(TNF_WELL_KNOWN, RTD_URI, null, recordBytes);
-    }
-
-    /**
-     * Create a new NDEF Record containing a URI.<p>
-     * Use this method to encode a URI (or URL) into an NDEF Record.<p>
-     * Uses the well known URI type representation: {@link #TNF_WELL_KNOWN}
-     * and {@link #RTD_URI}. This is the most efficient encoding
-     * of a URI into NDEF.<p>
-      * The uriString parameter will be normalized with
-     * {@link Uri#normalizeScheme} to set the scheme to lower case to
-     * follow Android best practices for intent filtering.
-     * However the unchecked exception
-     * {@link IllegalArgumentException} may be thrown if the uriString
-     * parameter has serious problems, for example if it is empty, so always
-     * catch this exception if you are passing user-generated data into this
-     * method.<p>
-     *
-     * Reference specification: NFCForum-TS-RTD_URI_1.0
-     *
-     * @param uriString string URI to encode.
-     * @return an NDEF Record containing the URI
-     * @throws IllegalArugmentException if the uriString is empty or invalid
-     */
-    public static NdefRecord createUri(String uriString) {
-        return createUri(Uri.parse(uriString));
-    }
-
-    /**
-     * Create a new NDEF Record containing MIME data.<p>
-     * Use this method to encode MIME-typed data into an NDEF Record,
-     * such as "text/plain", or "image/jpeg".<p>
-     * The mimeType parameter will be normalized with
-     * {@link Intent#normalizeMimeType} to follow Android best
-     * practices for intent filtering, for example to force lower-case.
-     * However the unchecked exception
-     * {@link IllegalArgumentException} may be thrown
-     * if the mimeType parameter has serious problems,
-     * for example if it is empty, so always catch this
-     * exception if you are passing user-generated data into this method.
-     * <p>
-     * For efficiency, This method might not make an internal copy of the
-     * mimeData byte array, so take care not
-     * to modify the mimeData byte array while still using the returned
-     * NdefRecord.
-     *
-     * @param mimeType a valid MIME type
-     * @param mimeData MIME data as bytes
-     * @return an NDEF Record containing the MIME-typed data
-     * @throws IllegalArugmentException if the mimeType is empty or invalid
-     *
-     */
-    public static NdefRecord createMime(String mimeType, byte[] mimeData) {
-        if (mimeType == null) throw new NullPointerException("mimeType is null");
-
-        // We only do basic MIME type validation: trying to follow the
-        // RFCs strictly only ends in tears, since there are lots of MIME
-        // types in common use that are not strictly valid as per RFC rules
-        mimeType = Intent.normalizeMimeType(mimeType);
-        if (mimeType.length() == 0) throw new IllegalArgumentException("mimeType is empty");
-        int slashIndex = mimeType.indexOf('/');
-        if (slashIndex == 0) throw new IllegalArgumentException("mimeType must have major type");
-        if (slashIndex == mimeType.length() - 1) {
-            throw new IllegalArgumentException("mimeType must have minor type");
-        }
-        // missing '/' is allowed
-
-        // MIME RFCs suggest ASCII encoding for content-type
-        byte[] typeBytes = mimeType.getBytes(StandardCharsets.US_ASCII);
-        return new NdefRecord(TNF_MIME_MEDIA, typeBytes, null, mimeData);
-    }
-
-    /**
-     * Create a new NDEF Record containing external (application-specific) data.<p>
-     * Use this method to encode application specific data into an NDEF Record.
-     * The data is typed by a domain name (usually your Android package name) and
-     * a domain-specific type. This data is packaged into a "NFC Forum External
-     * Type" NDEF Record.<p>
-     * NFC Forum requires that the domain and type used in an external record
-     * are treated as case insensitive, however Android intent filtering is
-     * always case sensitive. So this method will force the domain and type to
-     * lower-case before creating the NDEF Record.<p>
-     * The unchecked exception {@link IllegalArgumentException} will be thrown
-     * if the domain and type have serious problems, for example if either field
-     * is empty, so always catch this
-     * exception if you are passing user-generated data into this method.<p>
-     * There are no such restrictions on the payload data.<p>
-     * For efficiency, This method might not make an internal copy of the
-     * data byte array, so take care not
-     * to modify the data byte array while still using the returned
-     * NdefRecord.
-     *
-     * Reference specification: NFCForum-TS-RTD_1.0
-     * @param domain domain-name of issuing organization
-     * @param type domain-specific type of data
-     * @param data payload as bytes
-     * @throws IllegalArugmentException if either domain or type are empty or invalid
-     */
-    public static NdefRecord createExternal(String domain, String type, byte[] data) {
-        if (domain == null) throw new NullPointerException("domain is null");
-        if (type == null) throw new NullPointerException("type is null");
-
-        domain = domain.trim().toLowerCase(Locale.ROOT);
-        type = type.trim().toLowerCase(Locale.ROOT);
-
-        if (domain.length() == 0) throw new IllegalArgumentException("domain is empty");
-        if (type.length() == 0) throw new IllegalArgumentException("type is empty");
-
-        byte[] byteDomain = domain.getBytes(StandardCharsets.UTF_8);
-        byte[] byteType = type.getBytes(StandardCharsets.UTF_8);
-        byte[] b = new byte[byteDomain.length + 1 + byteType.length];
-        System.arraycopy(byteDomain, 0, b, 0, byteDomain.length);
-        b[byteDomain.length] = ':';
-        System.arraycopy(byteType, 0, b, byteDomain.length + 1, byteType.length);
-
-        return new NdefRecord(TNF_EXTERNAL_TYPE, b, null, data);
-    }
-
-    /**
-     * Create a new NDEF record containing UTF-8 text data.<p>
-     *
-     * The caller can either specify the language code for the provided text,
-     * or otherwise the language code corresponding to the current default
-     * locale will be used.
-     *
-     * Reference specification: NFCForum-TS-RTD_Text_1.0
-     * @param languageCode The languageCode for the record. If locale is empty or null,
-     *                     the language code of the current default locale will be used.
-     * @param text   The text to be encoded in the record. Will be represented in UTF-8 format.
-     * @throws IllegalArgumentException if text is null
-     */
-    public static NdefRecord createTextRecord(String languageCode, String text) {
-        if (text == null) throw new NullPointerException("text is null");
-
-        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
-
-        byte[] languageCodeBytes = null;
-        if (languageCode != null && !languageCode.isEmpty()) {
-            languageCodeBytes = languageCode.getBytes(StandardCharsets.US_ASCII);
-        } else {
-            languageCodeBytes = Locale.getDefault().getLanguage().
-                    getBytes(StandardCharsets.US_ASCII);
-        }
-        // We only have 6 bits to indicate ISO/IANA language code.
-        if (languageCodeBytes.length >= 64) {
-            throw new IllegalArgumentException("language code is too long, must be <64 bytes.");
-        }
-        ByteBuffer buffer = ByteBuffer.allocate(1 + languageCodeBytes.length + textBytes.length);
-
-        byte status = (byte) (languageCodeBytes.length & 0xFF);
-        buffer.put(status);
-        buffer.put(languageCodeBytes);
-        buffer.put(textBytes);
-
-        return new NdefRecord(TNF_WELL_KNOWN, RTD_TEXT, null, buffer.array());
-    }
-
-    /**
-     * Construct an NDEF Record from its component fields.<p>
-     * Recommend to use helpers such as {#createUri} or
-     * {{@link #createExternal} where possible, since they perform
-     * stricter validation that the record is correctly formatted
-     * as per NDEF specifications. However if you know what you are
-     * doing then this constructor offers the most flexibility.<p>
-     * An {@link NdefRecord} represents a logical (complete)
-     * record, and cannot represent NDEF Record chunks.<p>
-     * Basic validation of the tnf, type, id and payload is performed
-     * as per the following rules:
-     * <ul>
-     * <li>The tnf paramter must be a 3-bit value.</li>
-     * <li>Records with a tnf of {@link #TNF_EMPTY} cannot have a type,
-     * id or payload.</li>
-     * <li>Records with a tnf of {@link #TNF_UNKNOWN} or {@literal 0x07}
-     * cannot have a type.</li>
-     * <li>Records with a tnf of {@link #TNF_UNCHANGED} are not allowed
-     * since this class only represents complete (unchunked) records.</li>
-     * </ul>
-     * This minimal validation is specified by
-     * NFCForum-TS-NDEF_1.0 section 3.2.6 (Type Name Format).<p>
-     * If any of the above validation
-     * steps fail then {@link IllegalArgumentException} is thrown.<p>
-     * Deep inspection of the type, id and payload fields is not
-     * performed, so it is possible to create NDEF Records
-     * that conform to section 3.2.6
-     * but fail other more strict NDEF specification requirements. For
-     * example, the payload may be invalid given the tnf and type.
-     * <p>
-     * To omit a type, id or payload field, set the parameter to an
-     * empty byte array or null.
-     *
-     * @param tnf  a 3-bit TNF constant
-     * @param type byte array, containing zero to 255 bytes, or null
-     * @param id   byte array, containing zero to 255 bytes, or null
-     * @param payload byte array, containing zero to (2 ** 32 - 1) bytes,
-     *                or null
-     * @throws IllegalArugmentException if a valid record cannot be created
-     */
-    public NdefRecord(short tnf, byte[] type, byte[] id, byte[] payload) {
-        /* convert nulls */
-        if (type == null) type = EMPTY_BYTE_ARRAY;
-        if (id == null) id = EMPTY_BYTE_ARRAY;
-        if (payload == null) payload = EMPTY_BYTE_ARRAY;
-
-        String message = validateTnf(tnf, type, id, payload);
-        if (message != null) {
-            throw new IllegalArgumentException(message);
-        }
-
-        mTnf = tnf;
-        mType = type;
-        mId = id;
-        mPayload = payload;
-    }
-
-    /**
-     * Construct an NDEF Record from raw bytes.<p>
-     * This method is deprecated, use {@link NdefMessage#NdefMessage(byte[])}
-     * instead. This is because it does not make sense to parse a record:
-     * the NDEF binary format is only defined for a message, and the
-     * record flags MB and ME do not make sense outside of the context of
-     * an entire message.<p>
-     * This implementation will attempt to parse a single record by ignoring
-     * the MB and ME flags, and otherwise following the rules of
-     * {@link NdefMessage#NdefMessage(byte[])}.<p>
-     *
-     * @param data raw bytes to parse
-     * @throws FormatException if the data cannot be parsed into a valid record
-     * @deprecated use {@link NdefMessage#NdefMessage(byte[])} instead.
-     */
-    @Deprecated
-    public NdefRecord(byte[] data) throws FormatException {
-        ByteBuffer buffer = ByteBuffer.wrap(data);
-        NdefRecord[] rs = parse(buffer, true);
-
-        if (buffer.remaining() > 0) {
-            throw new FormatException("data too long");
-        }
-
-        mTnf = rs[0].mTnf;
-        mType = rs[0].mType;
-        mId = rs[0].mId;
-        mPayload = rs[0].mPayload;
-    }
-
-    /**
-     * Returns the 3-bit TNF.
-     * <p>
-     * TNF is the top-level type.
-     */
-    public short getTnf() {
-        return mTnf;
-    }
-
-    /**
-     * Returns the variable length Type field.
-     * <p>
-     * This should be used in conjunction with the TNF field to determine the
-     * payload format.
-     * <p>
-     * Returns an empty byte array if this record
-     * does not have a type field.
-     */
-    public byte[] getType() {
-        return mType.clone();
-    }
-
-    /**
-     * Returns the variable length ID.
-     * <p>
-     * Returns an empty byte array if this record
-     * does not have an id field.
-     */
-    public byte[] getId() {
-        return mId.clone();
-    }
-
-    /**
-     * Returns the variable length payload.
-     * <p>
-     * Returns an empty byte array if this record
-     * does not have a payload field.
-     */
-    public byte[] getPayload() {
-        return mPayload.clone();
-    }
-
-    /**
-     * Return this NDEF Record as a byte array.<p>
-     * This method is deprecated, use {@link NdefMessage#toByteArray}
-     * instead. This is because the NDEF binary format is not defined for
-     * a record outside of the context of a message: the MB and ME flags
-     * cannot be set without knowing the location inside a message.<p>
-     * This implementation will attempt to serialize a single record by
-     * always setting the MB and ME flags (in other words, assume this
-     * is a single-record NDEF Message).<p>
-     *
-     * @deprecated use {@link NdefMessage#toByteArray()} instead
-     */
-    @Deprecated
-    public byte[] toByteArray() {
-        ByteBuffer buffer = ByteBuffer.allocate(getByteLength());
-        writeToByteBuffer(buffer, true, true);
-        return buffer.array();
-    }
-
-    /**
-     * Map this record to a MIME type, or return null if it cannot be mapped.<p>
-     * Currently this method considers all {@link #TNF_MIME_MEDIA} records to
-     * be MIME records, as well as some {@link #TNF_WELL_KNOWN} records such as
-     * {@link #RTD_TEXT}. If this is a MIME record then the MIME type as string
-     * is returned, otherwise null is returned.<p>
-     * This method does not perform validation that the MIME type is
-     * actually valid. It always attempts to
-     * return a string containing the type if this is a MIME record.<p>
-     * The returned MIME type will by normalized to lower-case using
-     * {@link Intent#normalizeMimeType}.<p>
-     * The MIME payload can be obtained using {@link #getPayload}.
-     *
-     * @return MIME type as a string, or null if this is not a MIME record
-     */
-    public String toMimeType() {
-        switch (mTnf) {
-            case NdefRecord.TNF_WELL_KNOWN:
-                if (Arrays.equals(mType, NdefRecord.RTD_TEXT)) {
-                    return "text/plain";
-                }
-                break;
-            case NdefRecord.TNF_MIME_MEDIA:
-                String mimeType = new String(mType, StandardCharsets.US_ASCII);
-                return Intent.normalizeMimeType(mimeType);
-        }
-        return null;
-    }
-
-    /**
-     * Map this record to a URI, or return null if it cannot be mapped.<p>
-     * Currently this method considers the following to be URI records:
-     * <ul>
-     * <li>{@link #TNF_ABSOLUTE_URI} records.</li>
-     * <li>{@link #TNF_WELL_KNOWN} with a type of {@link #RTD_URI}.</li>
-     * <li>{@link #TNF_WELL_KNOWN} with a type of {@link #RTD_SMART_POSTER}
-     * and containing a URI record in the NDEF message nested in the payload.
-     * </li>
-     * <li>{@link #TNF_EXTERNAL_TYPE} records.</li>
-     * </ul>
-     * If this is not a URI record by the above rules, then null is returned.<p>
-     * This method does not perform validation that the URI is
-     * actually valid: it always attempts to create and return a URI if
-     * this record appears to be a URI record by the above rules.<p>
-     * The returned URI will be normalized to have a lower case scheme
-     * using {@link Uri#normalizeScheme}.<p>
-     *
-     * @return URI, or null if this is not a URI record
-     */
-    public Uri toUri() {
-        return toUri(false);
-    }
-
-    private Uri toUri(boolean inSmartPoster) {
-        switch (mTnf) {
-            case TNF_WELL_KNOWN:
-                if (Arrays.equals(mType, RTD_SMART_POSTER) && !inSmartPoster) {
-                    try {
-                        // check payload for a nested NDEF Message containing a URI
-                        NdefMessage nestedMessage = new NdefMessage(mPayload);
-                        for (NdefRecord nestedRecord : nestedMessage.getRecords()) {
-                            Uri uri = nestedRecord.toUri(true);
-                            if (uri != null) {
-                                return uri;
-                            }
-                        }
-                    } catch (FormatException e) {  }
-                } else if (Arrays.equals(mType, RTD_URI)) {
-                    Uri wktUri = parseWktUri();
-                    return (wktUri != null ? wktUri.normalizeScheme() : null);
-                }
-                break;
-
-            case TNF_ABSOLUTE_URI:
-                Uri uri = Uri.parse(new String(mType, StandardCharsets.UTF_8));
-                return uri.normalizeScheme();
-
-            case TNF_EXTERNAL_TYPE:
-                if (inSmartPoster) {
-                    break;
-                }
-                return Uri.parse("vnd.android.nfc://ext/" + new String(mType, StandardCharsets.US_ASCII));
-        }
-        return null;
-    }
-
-    /**
-     * Return complete URI of {@link #TNF_WELL_KNOWN}, {@link #RTD_URI} records.
-     * @return complete URI, or null if invalid
-     */
-    private Uri parseWktUri() {
-        if (mPayload.length < 2) {
-            return null;
-        }
-
-        // payload[0] contains the URI Identifier Code, as per
-        // NFC Forum "URI Record Type Definition" section 3.2.2.
-        int prefixIndex = (mPayload[0] & (byte)0xFF);
-        if (prefixIndex < 0 || prefixIndex >= URI_PREFIX_MAP.length) {
-            return null;
-        }
-        String prefix = URI_PREFIX_MAP[prefixIndex];
-        String suffix = new String(Arrays.copyOfRange(mPayload, 1, mPayload.length),
-                StandardCharsets.UTF_8);
-        return Uri.parse(prefix + suffix);
-    }
-
-    /**
-     * Main record parsing method.<p>
-     * Expects NdefMessage to begin immediately, allows trailing data.<p>
-     * Currently has strict validation of all fields as per NDEF 1.0
-     * specification section 2.5. We will attempt to keep this as strict as
-     * possible to encourage well-formatted NDEF.<p>
-     * Always returns 1 or more NdefRecord's, or throws FormatException.
-     *
-     * @param buffer ByteBuffer to read from
-     * @param ignoreMbMe ignore MB and ME flags, and read only 1 complete record
-     * @return one or more records
-     * @throws FormatException on any parsing error
-     */
-    static NdefRecord[] parse(ByteBuffer buffer, boolean ignoreMbMe) throws FormatException {
-        List<NdefRecord> records = new ArrayList<NdefRecord>();
-
-        try {
-            byte[] type = null;
-            byte[] id = null;
-            byte[] payload = null;
-            ArrayList<byte[]> chunks = new ArrayList<byte[]>();
-            boolean inChunk = false;
-            short chunkTnf = -1;
-            boolean me = false;
-
-            while (!me) {
-                byte flag = buffer.get();
-
-                boolean mb = (flag & NdefRecord.FLAG_MB) != 0;
-                me = (flag & NdefRecord.FLAG_ME) != 0;
-                boolean cf = (flag & NdefRecord.FLAG_CF) != 0;
-                boolean sr = (flag & NdefRecord.FLAG_SR) != 0;
-                boolean il = (flag & NdefRecord.FLAG_IL) != 0;
-                short tnf = (short)(flag & 0x07);
-
-                if (!mb && records.size() == 0 && !inChunk && !ignoreMbMe) {
-                    throw new FormatException("expected MB flag");
-                } else if (mb && (records.size() != 0 || inChunk) && !ignoreMbMe) {
-                    throw new FormatException("unexpected MB flag");
-                } else if (inChunk && il) {
-                    throw new FormatException("unexpected IL flag in non-leading chunk");
-                } else if (cf && me) {
-                    throw new FormatException("unexpected ME flag in non-trailing chunk");
-                } else if (inChunk && tnf != NdefRecord.TNF_UNCHANGED) {
-                    throw new FormatException("expected TNF_UNCHANGED in non-leading chunk");
-                } else if (!inChunk && tnf == NdefRecord.TNF_UNCHANGED) {
-                    throw new FormatException("" +
-                            "unexpected TNF_UNCHANGED in first chunk or unchunked record");
-                }
-
-                int typeLength = buffer.get() & 0xFF;
-                long payloadLength = sr ? (buffer.get() & 0xFF) : (buffer.getInt() & 0xFFFFFFFFL);
-                int idLength = il ? (buffer.get() & 0xFF) : 0;
-
-                if (inChunk && typeLength != 0) {
-                    throw new FormatException("expected zero-length type in non-leading chunk");
-                }
-
-                if (!inChunk) {
-                    type = (typeLength > 0 ? new byte[typeLength] : EMPTY_BYTE_ARRAY);
-                    id = (idLength > 0 ? new byte[idLength] : EMPTY_BYTE_ARRAY);
-                    buffer.get(type);
-                    buffer.get(id);
-                }
-
-                ensureSanePayloadSize(payloadLength);
-                payload = (payloadLength > 0 ? new byte[(int)payloadLength] : EMPTY_BYTE_ARRAY);
-                buffer.get(payload);
-
-                if (cf && !inChunk) {
-                    // first chunk
-                    if (typeLength == 0 && tnf != NdefRecord.TNF_UNKNOWN) {
-                        throw new FormatException("expected non-zero type length in first chunk");
-                    }
-                    chunks.clear();
-                    chunkTnf = tnf;
-                }
-                if (cf || inChunk) {
-                    // any chunk
-                    chunks.add(payload);
-                }
-                if (!cf && inChunk) {
-                    // last chunk, flatten the payload
-                    payloadLength = 0;
-                    for (byte[] p : chunks) {
-                        payloadLength += p.length;
-                    }
-                    ensureSanePayloadSize(payloadLength);
-                    payload = new byte[(int)payloadLength];
-                    int i = 0;
-                    for (byte[] p : chunks) {
-                        System.arraycopy(p, 0, payload, i, p.length);
-                        i += p.length;
-                    }
-                    tnf = chunkTnf;
-                }
-                if (cf) {
-                    // more chunks to come
-                    inChunk = true;
-                    continue;
-                } else {
-                    inChunk = false;
-                }
-
-                String error = validateTnf(tnf, type, id, payload);
-                if (error != null) {
-                    throw new FormatException(error);
-                }
-                records.add(new NdefRecord(tnf, type, id, payload));
-                if (ignoreMbMe) {  // for parsing a single NdefRecord
-                    break;
-                }
-            }
-        } catch (BufferUnderflowException e) {
-            throw new FormatException("expected more data", e);
-        }
-        return records.toArray(new NdefRecord[records.size()]);
-    }
-
-    private static void ensureSanePayloadSize(long size) throws FormatException {
-        if (size > MAX_PAYLOAD_SIZE) {
-            throw new FormatException(
-                    "payload above max limit: " + size + " > " + MAX_PAYLOAD_SIZE);
-        }
-    }
-
-    /**
-     * Perform simple validation that the tnf is valid.<p>
-     * Validates the requirements of NFCForum-TS-NDEF_1.0 section
-     * 3.2.6 (Type Name Format). This just validates that the tnf
-     * is valid, and that the relevant type, id and payload
-     * fields are present (or empty) for this tnf. It does not
-     * perform any deep inspection of the type, id and payload fields.<p>
-     * Also does not allow TNF_UNCHANGED since this class is only used
-     * to present logical (unchunked) records.
-     *
-     * @return null if valid, or a string error if invalid.
-     */
-    static String validateTnf(short tnf, byte[] type, byte[] id, byte[] payload) {
-        switch (tnf) {
-            case TNF_EMPTY:
-                if (type.length != 0 || id.length != 0 || payload.length != 0) {
-                    return "unexpected data in TNF_EMPTY record";
-                }
-                return null;
-            case TNF_WELL_KNOWN:
-            case TNF_MIME_MEDIA:
-            case TNF_ABSOLUTE_URI:
-            case TNF_EXTERNAL_TYPE:
-                return null;
-            case TNF_UNKNOWN:
-            case TNF_RESERVED:
-                if (type.length != 0) {
-                    return "unexpected type field in TNF_UNKNOWN or TNF_RESERVEd record";
-                }
-                return null;
-            case TNF_UNCHANGED:
-                return "unexpected TNF_UNCHANGED in first chunk or logical record";
-            default:
-                return String.format("unexpected tnf value: 0x%02x", tnf);
-        }
-    }
-
-    /**
-     * Serialize record for network transmission.<p>
-     * Uses specified MB and ME flags.<p>
-     * Does not chunk records.
-     */
-    void writeToByteBuffer(ByteBuffer buffer, boolean mb, boolean me) {
-        boolean sr = mPayload.length < 256;
-        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;
-
-        byte flags = (byte)((mb ? FLAG_MB : 0) | (me ? FLAG_ME : 0) |
-                (sr ? FLAG_SR : 0) | (il ? FLAG_IL : 0) | mTnf);
-        buffer.put(flags);
-
-        buffer.put((byte)mType.length);
-        if (sr) {
-            buffer.put((byte)mPayload.length);
-        } else {
-            buffer.putInt(mPayload.length);
-        }
-        if (il) {
-            buffer.put((byte)mId.length);
-        }
-
-        buffer.put(mType);
-        buffer.put(mId);
-        buffer.put(mPayload);
-    }
-
-    /**
-     * Get byte length of serialized record.
-     */
-    int getByteLength() {
-        int length = 3 + mType.length + mId.length + mPayload.length;
-
-        boolean sr = mPayload.length < 256;
-        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;
-
-        if (!sr) length += 3;
-        if (il) length += 1;
-
-        return length;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mTnf);
-        dest.writeInt(mType.length);
-        dest.writeByteArray(mType);
-        dest.writeInt(mId.length);
-        dest.writeByteArray(mId);
-        dest.writeInt(mPayload.length);
-        dest.writeByteArray(mPayload);
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<NdefRecord> CREATOR =
-            new Parcelable.Creator<NdefRecord>() {
-        @Override
-        public NdefRecord createFromParcel(Parcel in) {
-            short tnf = (short)in.readInt();
-            int typeLength = in.readInt();
-            byte[] type = new byte[typeLength];
-            in.readByteArray(type);
-            int idLength = in.readInt();
-            byte[] id = new byte[idLength];
-            in.readByteArray(id);
-            int payloadLength = in.readInt();
-            byte[] payload = new byte[payloadLength];
-            in.readByteArray(payload);
-
-            return new NdefRecord(tnf, type, id, payload);
-        }
-        @Override
-        public NdefRecord[] newArray(int size) {
-            return new NdefRecord[size];
-        }
-    };
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + Arrays.hashCode(mId);
-        result = prime * result + Arrays.hashCode(mPayload);
-        result = prime * result + mTnf;
-        result = prime * result + Arrays.hashCode(mType);
-        return result;
-    }
-
-    /**
-     * Returns true if the specified NDEF Record contains
-     * identical tnf, type, id and payload fields.
-     */
-    @Override
-    public boolean equals(@Nullable Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        NdefRecord other = (NdefRecord) obj;
-        if (!Arrays.equals(mId, other.mId)) return false;
-        if (!Arrays.equals(mPayload, other.mPayload)) return false;
-        if (mTnf != other.mTnf) return false;
-        return Arrays.equals(mType, other.mType);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder b = new StringBuilder(String.format("NdefRecord tnf=%X", mTnf));
-        if (mType.length > 0) b.append(" type=").append(bytesToString(mType));
-        if (mId.length > 0) b.append(" id=").append(bytesToString(mId));
-        if (mPayload.length > 0) b.append(" payload=").append(bytesToString(mPayload));
-        return b.toString();
-    }
-
-    /**
-     * Dump debugging information as a NdefRecordProto
-     * @hide
-     *
-     * Note:
-     * See proto definition in frameworks/base/core/proto/android/nfc/ndef.proto
-     * When writing a nested message, must call {@link ProtoOutputStream#start(long)} before and
-     * {@link ProtoOutputStream#end(long)} after.
-     * Never reuse a proto field number. When removing a field, mark it as reserved.
-     */
-    public void dumpDebug(ProtoOutputStream proto) {
-        proto.write(NdefRecordProto.TYPE, mType);
-        proto.write(NdefRecordProto.ID, mId);
-        proto.write(NdefRecordProto.PAYLOAD_BYTES, mPayload.length);
-    }
-
-    private static StringBuilder bytesToString(byte[] bs) {
-        StringBuilder s = new StringBuilder();
-        for (byte b : bs) {
-            s.append(String.format("%02X", b));
-        }
-        return s;
-    }
-}
diff --git a/nfc/java/android/nfc/NfcActivityManager.java b/nfc/java/android/nfc/NfcActivityManager.java
deleted file mode 100644
index 909eca7..0000000
--- a/nfc/java/android/nfc/NfcActivityManager.java
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.app.Activity;
-import android.app.Application;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.nfc.NfcAdapter.ReaderCallback;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Manages NFC API's that are coupled to the life-cycle of an Activity.
- *
- * <p>Uses {@link Application#registerActivityLifecycleCallbacks} to hook
- * into activity life-cycle events such as onPause() and onResume().
- *
- * @hide
- */
-public final class NfcActivityManager extends IAppCallback.Stub
-        implements Application.ActivityLifecycleCallbacks {
-    static final String TAG = NfcAdapter.TAG;
-    static final Boolean DBG = false;
-
-    @UnsupportedAppUsage
-    final NfcAdapter mAdapter;
-
-    // All objects in the lists are protected by this
-    final List<NfcApplicationState> mApps;  // Application(s) that have NFC state. Usually one
-    final List<NfcActivityState> mActivities;  // Activities that have NFC state
-
-    /**
-     * NFC State associated with an {@link Application}.
-     */
-    class NfcApplicationState {
-        int refCount = 0;
-        final Application app;
-        public NfcApplicationState(Application app) {
-            this.app = app;
-        }
-        public void register() {
-            refCount++;
-            if (refCount == 1) {
-                this.app.registerActivityLifecycleCallbacks(NfcActivityManager.this);
-            }
-        }
-        public void unregister() {
-            refCount--;
-            if (refCount == 0) {
-                this.app.unregisterActivityLifecycleCallbacks(NfcActivityManager.this);
-            } else if (refCount < 0) {
-                Log.e(TAG, "-ve refcount for " + app);
-            }
-        }
-    }
-
-    NfcApplicationState findAppState(Application app) {
-        for (NfcApplicationState appState : mApps) {
-            if (appState.app == app) {
-                return appState;
-            }
-        }
-        return null;
-    }
-
-    void registerApplication(Application app) {
-        NfcApplicationState appState = findAppState(app);
-        if (appState == null) {
-            appState = new NfcApplicationState(app);
-            mApps.add(appState);
-        }
-        appState.register();
-    }
-
-    void unregisterApplication(Application app) {
-        NfcApplicationState appState = findAppState(app);
-        if (appState == null) {
-            Log.e(TAG, "app was not registered " + app);
-            return;
-        }
-        appState.unregister();
-    }
-
-    /**
-     * NFC state associated with an {@link Activity}
-     */
-    class NfcActivityState {
-        boolean resumed = false;
-        Activity activity;
-        NfcAdapter.ReaderCallback readerCallback = null;
-        int readerModeFlags = 0;
-        Bundle readerModeExtras = null;
-        Binder token;
-
-        int mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
-        int mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
-
-        public NfcActivityState(Activity activity) {
-            if (activity.isDestroyed()) {
-                throw new IllegalStateException("activity is already destroyed");
-            }
-            // Check if activity is resumed right now, as we will not
-            // immediately get a callback for that.
-            resumed = activity.isResumed();
-
-            this.activity = activity;
-            this.token = new Binder();
-            registerApplication(activity.getApplication());
-        }
-        public void destroy() {
-            unregisterApplication(activity.getApplication());
-            resumed = false;
-            activity = null;
-            readerCallback = null;
-            readerModeFlags = 0;
-            readerModeExtras = null;
-            token = null;
-
-            mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
-            mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
-        }
-        @Override
-        public String toString() {
-            StringBuilder s = new StringBuilder("[");
-            s.append(readerCallback);
-            s.append("]");
-            return s.toString();
-        }
-    }
-
-    /** find activity state from mActivities */
-    synchronized NfcActivityState findActivityState(Activity activity) {
-        for (NfcActivityState state : mActivities) {
-            if (state.activity == activity) {
-                return state;
-            }
-        }
-        return null;
-    }
-
-    /** find or create activity state from mActivities */
-    synchronized NfcActivityState getActivityState(Activity activity) {
-        NfcActivityState state = findActivityState(activity);
-        if (state == null) {
-            state = new NfcActivityState(activity);
-            mActivities.add(state);
-        }
-        return state;
-    }
-
-    synchronized NfcActivityState findResumedActivityState() {
-        for (NfcActivityState state : mActivities) {
-            if (state.resumed) {
-                return state;
-            }
-        }
-        return null;
-    }
-
-    synchronized void destroyActivityState(Activity activity) {
-        NfcActivityState activityState = findActivityState(activity);
-        if (activityState != null) {
-            activityState.destroy();
-            mActivities.remove(activityState);
-        }
-    }
-
-    public NfcActivityManager(NfcAdapter adapter) {
-        mAdapter = adapter;
-        mActivities = new LinkedList<NfcActivityState>();
-        mApps = new ArrayList<NfcApplicationState>(1);  // Android VM usually has 1 app
-    }
-
-    public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
-            Bundle extras) {
-        boolean isResumed;
-        Binder token;
-        int pollTech, listenTech;
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = getActivityState(activity);
-            state.readerCallback = callback;
-            state.readerModeFlags = flags;
-            state.readerModeExtras = extras;
-            pollTech = state.mPollTech;
-            listenTech = state.mListenTech;
-            token = state.token;
-            isResumed = state.resumed;
-        }
-        if (isResumed) {
-            if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
-                    || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
-                throw new IllegalStateException(
-                    "Cannot be used when alternative DiscoveryTechnology is set");
-            } else {
-                setReaderMode(token, flags, extras);
-            }
-        }
-    }
-
-    public void disableReaderMode(Activity activity) {
-        boolean isResumed;
-        Binder token;
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = getActivityState(activity);
-            state.readerCallback = null;
-            state.readerModeFlags = 0;
-            state.readerModeExtras = null;
-            token = state.token;
-            isResumed = state.resumed;
-        }
-        if (isResumed) {
-            setReaderMode(token, 0, null);
-        }
-
-    }
-
-    public void setReaderMode(Binder token, int flags, Bundle extras) {
-        if (DBG) Log.d(TAG, "Setting reader mode");
-        NfcAdapter.callService(() -> NfcAdapter.sService.setReaderMode(
-                token, this, flags, extras, mAdapter.getContext().getPackageName()));
-    }
-
-    /**
-     * Request or unrequest NFC service callbacks.
-     * Makes IPC call - do not hold lock.
-     */
-    void requestNfcServiceCallback() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.setAppCallback(this));
-    }
-
-    void verifyNfcPermission() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.verifyNfcPermission());
-    }
-
-    @Override
-    public void onTagDiscovered(Tag tag) throws RemoteException {
-        NfcAdapter.ReaderCallback callback;
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = findResumedActivityState();
-            if (state == null) return;
-
-            callback = state.readerCallback;
-        }
-
-        // Make callback without lock
-        if (callback != null) {
-            callback.onTagDiscovered(tag);
-        }
-
-    }
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { /* NO-OP */ }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityStarted(Activity activity) { /* NO-OP */ }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityResumed(Activity activity) {
-        int readerModeFlags = 0;
-        Bundle readerModeExtras = null;
-        Binder token;
-        int pollTech;
-        int listenTech;
-
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = findActivityState(activity);
-            if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
-            if (state == null) return;
-            state.resumed = true;
-            token = state.token;
-            readerModeFlags = state.readerModeFlags;
-            readerModeExtras = state.readerModeExtras;
-
-            pollTech = state.mPollTech;
-            listenTech = state.mListenTech;
-        }
-        if (readerModeFlags != 0) {
-            setReaderMode(token, readerModeFlags, readerModeExtras);
-        } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
-                || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
-            changeDiscoveryTech(token, pollTech, listenTech);
-        }
-        requestNfcServiceCallback();
-    }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityPaused(Activity activity) {
-        boolean readerModeFlagsSet;
-        Binder token;
-        int pollTech;
-        int listenTech;
-
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = findActivityState(activity);
-            if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
-            if (state == null) return;
-            state.resumed = false;
-            token = state.token;
-            readerModeFlagsSet = state.readerModeFlags != 0;
-
-            pollTech = state.mPollTech;
-            listenTech = state.mListenTech;
-        }
-        if (readerModeFlagsSet) {
-            // Restore default p2p modes
-            setReaderMode(token, 0, null);
-        } else if (listenTech != NfcAdapter.FLAG_USE_ALL_TECH
-                || pollTech != NfcAdapter.FLAG_USE_ALL_TECH) {
-            changeDiscoveryTech(token,
-                    NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
-        }
-    }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityStopped(Activity activity) { /* NO-OP */ }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivitySaveInstanceState(Activity activity, Bundle outState) { /* NO-OP */ }
-
-    /** Callback from Activity life-cycle, on main thread */
-    @Override
-    public void onActivityDestroyed(Activity activity) {
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = findActivityState(activity);
-            if (DBG) Log.d(TAG, "onDestroy() for " + activity + " " + state);
-            if (state != null) {
-                // release all associated references
-                destroyActivityState(activity);
-            }
-        }
-    }
-
-    /** setDiscoveryTechnology() implementation */
-    public void setDiscoveryTech(Activity activity, int pollTech, int listenTech) {
-        boolean isResumed;
-        Binder token;
-        boolean readerModeFlagsSet;
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = getActivityState(activity);
-            readerModeFlagsSet = state.readerModeFlags != 0;
-            state.mListenTech = listenTech;
-            state.mPollTech = pollTech;
-            token = state.token;
-            isResumed = state.resumed;
-        }
-        if (!readerModeFlagsSet && isResumed) {
-            changeDiscoveryTech(token, pollTech, listenTech);
-        } else if (readerModeFlagsSet) {
-            throw new IllegalStateException("Cannot be used when the Reader Mode is enabled");
-        }
-    }
-
-    /** resetDiscoveryTechnology() implementation */
-    public void resetDiscoveryTech(Activity activity) {
-        boolean isResumed;
-        Binder token;
-        boolean readerModeFlagsSet;
-        synchronized (NfcActivityManager.this) {
-            NfcActivityState state = getActivityState(activity);
-            state.mListenTech = NfcAdapter.FLAG_USE_ALL_TECH;
-            state.mPollTech = NfcAdapter.FLAG_USE_ALL_TECH;
-            token = state.token;
-            isResumed = state.resumed;
-        }
-        if (isResumed) {
-            changeDiscoveryTech(token, NfcAdapter.FLAG_USE_ALL_TECH, NfcAdapter.FLAG_USE_ALL_TECH);
-        }
-
-    }
-
-    private void changeDiscoveryTech(Binder token, int pollTech, int listenTech) {
-        NfcAdapter.callService(
-                () -> NfcAdapter.sService.updateDiscoveryTechnology(
-                        token, pollTech, listenTech, mAdapter.getContext().getPackageName()));
-    }
-
-}
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
deleted file mode 100644
index 63397c2..0000000
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ /dev/null
@@ -1,2949 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.annotation.TestApi;
-import android.annotation.UserIdInt;
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.nfc.cardemulation.PollingFrame;
-import android.nfc.tech.MifareClassic;
-import android.nfc.tech.Ndef;
-import android.nfc.tech.NfcA;
-import android.nfc.tech.NfcF;
-import android.os.Binder;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Log;
-
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * Represents the local NFC adapter.
- * <p>
- * Use the helper {@link #getDefaultAdapter(Context)} to get the default NFC
- * adapter for this Android device.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using NFC, read the
- * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
- * <p>To perform basic file sharing between devices, read
- * <a href="{@docRoot}training/beam-files/index.html">Sharing Files with NFC</a>.
- * </div>
- */
-public final class NfcAdapter {
-    static final String TAG = "NFC";
-
-    private final NfcControllerAlwaysOnListener mControllerAlwaysOnListener;
-    private final NfcWlcStateListener mNfcWlcStateListener;
-    private final NfcVendorNciCallbackListener mNfcVendorNciCallbackListener;
-
-    /**
-     * Intent to start an activity when a tag with NDEF payload is discovered.
-     *
-     * <p>The system inspects the first {@link NdefRecord} in the first {@link NdefMessage} and
-     * looks for a URI, SmartPoster, or MIME record. If a URI or SmartPoster record is found the
-     * intent will contain the URI in its data field. If a MIME record is found the intent will
-     * contain the MIME type in its type field. This allows activities to register
-     * {@link IntentFilter}s targeting specific content on tags. Activities should register the
-     * most specific intent filters possible to avoid the activity chooser dialog, which can
-     * disrupt the interaction with the tag as the user interacts with the screen.
-     *
-     * <p>If the tag has an NDEF payload this intent is started before
-     * {@link #ACTION_TECH_DISCOVERED}. If any activities respond to this intent neither
-     * {@link #ACTION_TECH_DISCOVERED} or {@link #ACTION_TAG_DISCOVERED} will be started.
-     *
-     * <p>The MIME type or data URI of this intent are normalized before dispatch -
-     * so that MIME, URI scheme and URI host are always lower-case.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED";
-
-    /**
-     * Intent to start an activity when a tag is discovered and activities are registered for the
-     * specific technologies on the tag.
-     *
-     * <p>To receive this intent an activity must include an intent filter
-     * for this action and specify the desired tech types in a
-     * manifest <code>meta-data</code> entry. Here is an example manfiest entry:
-     * <pre>
-     * &lt;activity android:name=".nfc.TechFilter" android:label="NFC/TechFilter"&gt;
-     *     &lt;!-- Add a technology filter --&gt;
-     *     &lt;intent-filter&gt;
-     *         &lt;action android:name="android.nfc.action.TECH_DISCOVERED" /&gt;
-     *     &lt;/intent-filter&gt;
-     *
-     *     &lt;meta-data android:name="android.nfc.action.TECH_DISCOVERED"
-     *         android:resource="@xml/filter_nfc"
-     *     /&gt;
-     * &lt;/activity&gt;</pre>
-     *
-     * <p>The meta-data XML file should contain one or more <code>tech-list</code> entries
-     * each consisting or one or more <code>tech</code> entries. The <code>tech</code> entries refer
-     * to the qualified class name implementing the technology, for example "android.nfc.tech.NfcA".
-     *
-     * <p>A tag matches if any of the
-     * <code>tech-list</code> sets is a subset of {@link Tag#getTechList() Tag.getTechList()}. Each
-     * of the <code>tech-list</code>s is considered independently and the
-     * activity is considered a match is any single <code>tech-list</code> matches the tag that was
-     * discovered. This provides AND and OR semantics for filtering desired techs. Here is an
-     * example that will match any tag using {@link NfcF} or any tag using {@link NfcA},
-     * {@link MifareClassic}, and {@link Ndef}:
-     *
-     * <pre>
-     * &lt;resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"&gt;
-     *     &lt;!-- capture anything using NfcF --&gt;
-     *     &lt;tech-list&gt;
-     *         &lt;tech&gt;android.nfc.tech.NfcF&lt;/tech&gt;
-     *     &lt;/tech-list&gt;
-     *
-     *     &lt;!-- OR --&gt;
-     *
-     *     &lt;!-- capture all MIFARE Classics with NDEF payloads --&gt;
-     *     &lt;tech-list&gt;
-     *         &lt;tech&gt;android.nfc.tech.NfcA&lt;/tech&gt;
-     *         &lt;tech&gt;android.nfc.tech.MifareClassic&lt;/tech&gt;
-     *         &lt;tech&gt;android.nfc.tech.Ndef&lt;/tech&gt;
-     *     &lt;/tech-list&gt;
-     * &lt;/resources&gt;</pre>
-     *
-     * <p>This intent is started after {@link #ACTION_NDEF_DISCOVERED} and before
-     * {@link #ACTION_TAG_DISCOVERED}. If any activities respond to {@link #ACTION_NDEF_DISCOVERED}
-     * this intent will not be started. If any activities respond to this intent
-     * {@link #ACTION_TAG_DISCOVERED} will not be started.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED";
-
-    /**
-     * Intent to start an activity when a tag is discovered.
-     *
-     * <p>This intent will not be started when a tag is discovered if any activities respond to
-     * {@link #ACTION_NDEF_DISCOVERED} or {@link #ACTION_TECH_DISCOVERED} for the current tag.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
-
-    /**
-     * Broadcast Action: Intent to notify an application that a transaction event has occurred
-     * on the Secure Element.
-     *
-     * <p>This intent will only be sent if the application has requested permission for
-     * {@link android.Manifest.permission#NFC_TRANSACTION_EVENT} and if the application has the
-     * necessary access to Secure Element which witnessed the particular event.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC_TRANSACTION_EVENT)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_TRANSACTION_DETECTED =
-            "android.nfc.action.TRANSACTION_DETECTED";
-
-    /**
-     * Broadcast Action: Intent to notify if the preferred payment service changed.
-     *
-     * <p>This intent will only be sent to the application has requested permission for
-     * {@link android.Manifest.permission#NFC_PREFERRED_PAYMENT_INFO} and if the application
-     * has the necessary access to Secure Element which witnessed the particular event.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_PREFERRED_PAYMENT_CHANGED =
-            "android.nfc.action.PREFERRED_PAYMENT_CHANGED";
-
-    /**
-     * Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
-     * @hide
-     */
-    public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST";
-
-    /**
-     * Mandatory extra containing the {@link Tag} that was discovered for the
-     * {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
-     * {@link #ACTION_TAG_DISCOVERED} intents.
-     */
-    public static final String EXTRA_TAG = "android.nfc.extra.TAG";
-
-    /**
-     * Extra containing an array of {@link NdefMessage} present on the discovered tag.<p>
-     * This extra is mandatory for {@link #ACTION_NDEF_DISCOVERED} intents,
-     * and optional for {@link #ACTION_TECH_DISCOVERED}, and
-     * {@link #ACTION_TAG_DISCOVERED} intents.<p>
-     * When this extra is present there will always be at least one
-     * {@link NdefMessage} element. Most NDEF tags have only one NDEF message,
-     * but we use an array for future compatibility.
-     */
-    public static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
-
-    /**
-     * Optional extra containing a byte array containing the ID of the discovered tag for
-     * the {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED}, and
-     * {@link #ACTION_TAG_DISCOVERED} intents.
-     */
-    public static final String EXTRA_ID = "android.nfc.extra.ID";
-
-    /**
-     * Broadcast Action: The state of the local NFC adapter has been
-     * changed.
-     * <p>For example, NFC has been turned on or off.
-     * <p>Always contains the extra field {@link #EXTRA_ADAPTER_STATE}
-     */
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_ADAPTER_STATE_CHANGED =
-            "android.nfc.action.ADAPTER_STATE_CHANGED";
-
-    /**
-     * Used as an int extra field in {@link #ACTION_ADAPTER_STATE_CHANGED}
-     * intents to request the current power state. Possible values are:
-     * {@link #STATE_OFF},
-     * {@link #STATE_TURNING_ON},
-     * {@link #STATE_ON},
-     * {@link #STATE_TURNING_OFF},
-     */
-    public static final String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE";
-
-    /**
-     * Mandatory byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
-     */
-    public static final String EXTRA_AID = "android.nfc.extra.AID";
-
-    /**
-     * Optional byte[] extra field in {@link #ACTION_TRANSACTION_DETECTED}
-     */
-    public static final String EXTRA_DATA = "android.nfc.extra.DATA";
-
-    /**
-     * Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED}
-     * Indicates the Secure Element on which the transaction occurred.
-     * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC/EUICC, etc.
-     */
-    public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
-
-    /**
-     * Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED}
-     * Indicates the condition when trigger this event. Possible values are:
-     * {@link #PREFERRED_PAYMENT_LOADED},
-     * {@link #PREFERRED_PAYMENT_CHANGED},
-     * {@link #PREFERRED_PAYMENT_UPDATED},
-     */
-    public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON =
-            "android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
-    /**
-     * Nfc is enabled and the preferred payment aids are registered.
-     */
-    public static final int PREFERRED_PAYMENT_LOADED = 1;
-    /**
-     * User selected another payment application as the preferred payment.
-     */
-    public static final int PREFERRED_PAYMENT_CHANGED = 2;
-    /**
-     * Current preferred payment has issued an update (registered/unregistered new aids or has been
-     * updated itself).
-     */
-    public static final int PREFERRED_PAYMENT_UPDATED = 3;
-
-    public static final int STATE_OFF = 1;
-    public static final int STATE_TURNING_ON = 2;
-    public static final int STATE_ON = 3;
-    public static final int STATE_TURNING_OFF = 4;
-
-    /**
-     * Possible states from {@link #getAdapterState}.
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "STATE_" }, value = {
-            STATE_OFF,
-            STATE_TURNING_ON,
-            STATE_ON,
-            STATE_TURNING_OFF
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface AdapterState{}
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag enables polling for Nfc-A technology.
-     */
-    public static final int FLAG_READER_NFC_A = 0x1;
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag enables polling for Nfc-B technology.
-     */
-    public static final int FLAG_READER_NFC_B = 0x2;
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag enables polling for Nfc-F technology.
-     */
-    public static final int FLAG_READER_NFC_F = 0x4;
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag enables polling for Nfc-V (ISO15693) technology.
-     */
-    public static final int FLAG_READER_NFC_V = 0x8;
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag enables polling for NfcBarcode technology.
-     */
-    public static final int FLAG_READER_NFC_BARCODE = 0x10;
-
-    /** @hide */
-    @IntDef(flag = true, value = {
-        FLAG_SET_DEFAULT_TECH,
-        FLAG_READER_KEEP,
-        FLAG_READER_DISABLE,
-        FLAG_READER_NFC_A,
-        FLAG_READER_NFC_B,
-        FLAG_READER_NFC_F,
-        FLAG_READER_NFC_V,
-        FLAG_READER_NFC_BARCODE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface PollTechnology {}
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag allows the caller to prevent the
-     * platform from performing an NDEF check on the tags it
-     * finds.
-     */
-    public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80;
-
-    /**
-     * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this flag allows the caller to prevent the
-     * platform from playing sounds when it discovers a tag.
-     */
-    public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100;
-
-    /**
-     * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}.
-     * <p>
-     * Setting this integer extra allows the calling application to specify
-     * the delay that the platform will use for performing presence checks
-     * on any discovered tag.
-     */
-    public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
-
-    /**
-     * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag enables listening for Nfc-A technology.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_LISTEN_NFC_PASSIVE_A = 0x1;
-
-    /**
-     * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag enables listening for Nfc-B technology.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_LISTEN_NFC_PASSIVE_B = 1 << 1;
-
-    /**
-     * Flag for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag enables listening for Nfc-F technology.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_LISTEN_NFC_PASSIVE_F = 1 << 2;
-
-    /**
-     * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag disables listening.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_LISTEN_DISABLE = 0x0;
-
-    /**
-     * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag disables polling.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_READER_DISABLE = 0x0;
-
-    /**
-     * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag makes listening to keep the current technology configuration.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_LISTEN_KEEP = 0x80000000;
-
-    /**
-     * Flags for use with {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag makes polling to keep the current technology configuration.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public static final int FLAG_READER_KEEP = 0x80000000;
-
-    /** @hide */
-    public static final int FLAG_USE_ALL_TECH = 0xff;
-
-    /** @hide */
-    @IntDef(flag = true, value = {
-        FLAG_SET_DEFAULT_TECH,
-        FLAG_LISTEN_KEEP,
-        FLAG_LISTEN_DISABLE,
-        FLAG_LISTEN_NFC_PASSIVE_A,
-        FLAG_LISTEN_NFC_PASSIVE_B,
-        FLAG_LISTEN_NFC_PASSIVE_F
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ListenTechnology {}
-
-    /**
-     * Flag used in {@link #setDiscoveryTechnology(Activity, int, int)}.
-     * <p>
-     * Setting this flag changes the default listen or poll tech.
-     * Only available to privileged apps.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH)
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    public static final int FLAG_SET_DEFAULT_TECH = 0x40000000;
-
-    /**
-     * @hide
-     * @removed
-     */
-    @SystemApi
-    @UnsupportedAppUsage
-    public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1;
-
-    /** @hide */
-    public static final String ACTION_HANDOVER_TRANSFER_STARTED =
-            "android.nfc.action.HANDOVER_TRANSFER_STARTED";
-
-    /** @hide */
-    public static final String ACTION_HANDOVER_TRANSFER_DONE =
-            "android.nfc.action.HANDOVER_TRANSFER_DONE";
-
-    /** @hide */
-    public static final String EXTRA_HANDOVER_TRANSFER_STATUS =
-            "android.nfc.extra.HANDOVER_TRANSFER_STATUS";
-
-    /** @hide */
-    public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
-    /** @hide */
-    public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;
-
-    /** @hide */
-    public static final String EXTRA_HANDOVER_TRANSFER_URI =
-            "android.nfc.extra.HANDOVER_TRANSFER_URI";
-
-    /**
-     * Broadcast Action: Notify possible NFC transaction blocked because device is locked.
-     * <p>An external NFC field detected when device locked and SecureNfc enabled.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public static final String ACTION_REQUIRE_UNLOCK_FOR_NFC =
-            "android.nfc.action.REQUIRE_UNLOCK_FOR_NFC";
-
-    /**
-     * Intent action to start a NFC resolver activity in a customized share session with list of
-     * {@link ResolveInfo}.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    @RequiresPermission(Manifest.permission.SHOW_CUSTOMIZED_RESOLVER)
-    public static final String ACTION_SHOW_NFC_RESOLVER = "android.nfc.action.SHOW_NFC_RESOLVER";
-
-    /**
-     * "Extras" key for an ArrayList of {@link ResolveInfo} records which are to be shown as the
-     * targets in the customized share session.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public static final String EXTRA_RESOLVE_INFOS = "android.nfc.extra.RESOLVE_INFOS";
-
-    /**
-     * The requested app is correctly added to the Tag intent app preference.
-     *
-     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
-     * @hide
-     */
-    @SystemApi
-    public static final int TAG_INTENT_APP_PREF_RESULT_SUCCESS = 0;
-
-    /**
-     * The requested app is not installed on the device.
-     *
-     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
-     * @hide
-     */
-    @SystemApi
-    public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1;
-
-    /**
-     * The NfcService is not available.
-     *
-     * @see #setTagIntentAppPreferenceForUser(int userId, String pkg, boolean allow)
-     * @hide
-     */
-    @SystemApi
-    public static final int TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE = -2;
-
-    /**
-     * Possible response codes from {@link #setTagIntentAppPreferenceForUser}.
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "TAG_INTENT_APP_PREF_RESULT" }, value = {
-            TAG_INTENT_APP_PREF_RESULT_SUCCESS,
-            TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND,
-            TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface TagIntentAppPreferenceResult {}
-
-    /**
-     * Mode Type for {@link NfcOemExtension#setControllerAlwaysOnMode(int)}.
-     * @hide
-     */
-    public static final int CONTROLLER_ALWAYS_ON_MODE_DEFAULT = 1;
-
-    /**
-     * Mode Type for {@link NfcOemExtension#setControllerAlwaysOnMode(int)}.
-     * @hide
-     */
-    public static final int CONTROLLER_ALWAYS_ON_DISABLE = 0;
-
-    // Guarded by sLock
-    static boolean sIsInitialized = false;
-    static boolean sHasNfcFeature;
-    static boolean sHasCeFeature;
-    static boolean sHasNfcWlcFeature;
-
-    static Object sLock = new Object();
-
-    // Final after first constructor, except for
-    // attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
-    // recovery
-    @UnsupportedAppUsage
-    static INfcAdapter sService;
-    static NfcServiceManager.ServiceRegisterer sServiceRegisterer;
-    static INfcTag sTagService;
-    static INfcCardEmulation sCardEmulationService;
-    static INfcFCardEmulation sNfcFCardEmulationService;
-    static IT4tNdefNfcee sNdefNfceeService;
-
-    /**
-     * The NfcAdapter object for each application context.
-     * There is a 1-1 relationship between application context and
-     * NfcAdapter object.
-     */
-    static HashMap<Context, NfcAdapter> sNfcAdapters = new HashMap(); //guard by NfcAdapter.class
-
-    /**
-     * NfcAdapter used with a null context. This ctor was deprecated but we have
-     * to support it for backwards compatibility. New methods that require context
-     * might throw when called on the null-context NfcAdapter.
-     */
-    static NfcAdapter sNullContextNfcAdapter;  // protected by NfcAdapter.class
-
-    final NfcActivityManager mNfcActivityManager;
-    final Context mContext;
-    final HashMap<NfcUnlockHandler, INfcUnlockHandler> mNfcUnlockHandlers;
-    final Object mLock;
-    final NfcOemExtension mNfcOemExtension;
-
-    ITagRemovedCallback mTagRemovedListener; // protected by mLock
-
-    /**
-     * A callback to be invoked when the system finds a tag while the foreground activity is
-     * operating in reader mode.
-     * <p>Register your {@code ReaderCallback} implementation with {@link
-     * NfcAdapter#enableReaderMode} and disable it with {@link
-     * NfcAdapter#disableReaderMode}.
-     * @see NfcAdapter#enableReaderMode
-     */
-    public interface ReaderCallback {
-        public void onTagDiscovered(Tag tag);
-    }
-
-    /**
-     * A listener to be invoked when NFC controller always on state changes.
-     * <p>Register your {@code ControllerAlwaysOnListener} implementation with {@link
-     * NfcAdapter#registerControllerAlwaysOnListener} and disable it with {@link
-     * NfcAdapter#unregisterControllerAlwaysOnListener}.
-     * @see #registerControllerAlwaysOnListener
-     * @hide
-     */
-    @SystemApi
-    public interface ControllerAlwaysOnListener {
-        /**
-         * Called on NFC controller always on state changes
-         */
-        void onControllerAlwaysOnChanged(boolean isEnabled);
-    }
-
-    /**
-     * A callback to be invoked when the system successfully delivers your {@link NdefMessage}
-     * to another device.
-     * @deprecated this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    public interface OnNdefPushCompleteCallback {
-        /**
-         * Called on successful NDEF push.
-         *
-         * <p>This callback is usually made on a binder thread (not the UI thread).
-         *
-         * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
-         */
-        public void onNdefPushComplete(NfcEvent event);
-    }
-
-    /**
-     * A callback to be invoked when another NFC device capable of NDEF push (Android Beam)
-     * is within range.
-     * <p>Implement this interface and pass it to {@code
-     * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an
-     * {@link NdefMessage} at the moment that another device is within range for NFC. Using this
-     * callback allows you to create a message with data that might vary based on the
-     * content currently visible to the user. Alternatively, you can call {@code
-     * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
-     * same data.
-     * @deprecated this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    public interface CreateNdefMessageCallback {
-        /**
-         * Called to provide a {@link NdefMessage} to push.
-         *
-         * <p>This callback is usually made on a binder thread (not the UI thread).
-         *
-         * <p>Called when this device is in range of another device
-         * that might support NDEF push. It allows the application to
-         * create the NDEF message only when it is required.
-         *
-         * <p>NDEF push cannot occur until this method returns, so do not
-         * block for too long.
-         *
-         * <p>The Android operating system will usually show a system UI
-         * on top of your activity during this time, so do not try to request
-         * input from the user to complete the callback, or provide custom NDEF
-         * push UI. The user probably will not see it.
-         *
-         * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
-         * @return NDEF message to push, or null to not provide a message
-         */
-        public NdefMessage createNdefMessage(NfcEvent event);
-    }
-
-
-     /**
-     * @deprecated this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    public interface CreateBeamUrisCallback {
-        public Uri[] createBeamUris(NfcEvent event);
-    }
-
-    /**
-     * A callback that is invoked when a tag is removed from the field.
-     * @see NfcAdapter#ignore
-     */
-    public interface OnTagRemovedListener {
-        void onTagRemoved();
-    }
-
-    /**
-     * A callback to be invoked when an application has registered as a
-     * handler to unlock the device given an NFC tag at the lockscreen.
-     * @hide
-     */
-    @SystemApi
-    public interface NfcUnlockHandler {
-        /**
-         * Called at the lock screen to attempt to unlock the device with the given tag.
-         * @param tag the detected tag, to be used to unlock the device
-         * @return true if the device was successfully unlocked
-         */
-        public boolean onUnlockAttempted(Tag tag);
-    }
-
-    /**
-     * Return list of Secure Elements which support off host card emulation.
-     *
-     * @return List<String> containing secure elements on the device which supports
-     *                      off host card emulation. eSE for Embedded secure element,
-     *                      SIM for UICC/EUICC and so on.
-     * @hide
-     */
-    public @NonNull List<String> getSupportedOffHostSecureElements() {
-        if (mContext == null) {
-            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
-                    + " getSupportedOffHostSecureElements APIs");
-        }
-        List<String> offHostSE = new ArrayList<String>();
-        PackageManager pm = mContext.getPackageManager();
-        if (pm == null) {
-            Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature");
-            return offHostSE;
-        }
-        if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)) {
-            offHostSE.add("SIM");
-        }
-        if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE)) {
-            offHostSE.add("eSE");
-        }
-        return offHostSE;
-    }
-
-    private static void retrieveServiceRegisterer() {
-        if (sServiceRegisterer == null) {
-            NfcServiceManager manager = NfcFrameworkInitializer.getNfcServiceManager();
-            if (manager == null) {
-                Log.e(TAG, "NfcServiceManager is null");
-                throw new UnsupportedOperationException();
-            }
-            sServiceRegisterer = manager.getNfcManagerServiceRegisterer();
-        }
-    }
-
-    /**
-     * Returns the NfcAdapter for application context,
-     * or throws if NFC is not available.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static synchronized NfcAdapter getNfcAdapter(Context context) {
-        if (context == null) {
-            if (sNullContextNfcAdapter == null) {
-                sNullContextNfcAdapter = new NfcAdapter(null);
-            }
-            return sNullContextNfcAdapter;
-        }
-        if (!sIsInitialized) {
-            PackageManager pm;
-            pm = context.getPackageManager();
-            sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC);
-            sHasCeFeature =
-                    pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)
-                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)
-                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)
-                    || pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE);
-            sHasNfcWlcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_CHARGING);
-            /* is this device meant to have NFC */
-            if (!sHasNfcFeature && !sHasCeFeature && !sHasNfcWlcFeature) {
-                Log.v(TAG, "this device does not have NFC support");
-                throw new UnsupportedOperationException();
-            }
-            retrieveServiceRegisterer();
-            sService = getServiceInterface();
-            if (sService == null) {
-                Log.e(TAG, "could not retrieve NFC service");
-                throw new UnsupportedOperationException();
-            }
-            if (sHasNfcFeature) {
-                try {
-                    sTagService = sService.getNfcTagInterface();
-                } catch (RemoteException e) {
-                    sTagService = null;
-                    Log.e(TAG, "could not retrieve NFC Tag service");
-                    throw new UnsupportedOperationException();
-                }
-            }
-            if (sHasCeFeature) {
-                try {
-                    sNfcFCardEmulationService = sService.getNfcFCardEmulationInterface();
-                } catch (RemoteException e) {
-                    sNfcFCardEmulationService = null;
-                    Log.e(TAG, "could not retrieve NFC-F card emulation service");
-                    throw new UnsupportedOperationException();
-                }
-                try {
-                    sCardEmulationService = sService.getNfcCardEmulationInterface();
-                } catch (RemoteException e) {
-                    sCardEmulationService = null;
-                    Log.e(TAG, "could not retrieve card emulation service");
-                    throw new UnsupportedOperationException();
-                }
-            }
-            try {
-                sNdefNfceeService = sService.getT4tNdefNfceeInterface();
-            } catch (RemoteException e) {
-                sNdefNfceeService = null;
-                Log.e(TAG, "could not retrieve NDEF NFCEE service");
-                throw new UnsupportedOperationException();
-            }
-            sIsInitialized = true;
-        }
-        NfcAdapter adapter = sNfcAdapters.get(context);
-        if (adapter == null) {
-            adapter = new NfcAdapter(context);
-            sNfcAdapters.put(context, adapter);
-        }
-        return adapter;
-    }
-
-    /** get handle to NFC service interface */
-    private static INfcAdapter getServiceInterface() {
-        /* get a handle to NFC service */
-        IBinder b = sServiceRegisterer.get();
-        if (b == null) {
-            return null;
-        }
-        return INfcAdapter.Stub.asInterface(b);
-    }
-
-    /**
-     * Helper to get the default NFC Adapter.
-     * <p>
-     * Most Android devices will only have one NFC Adapter (NFC Controller).
-     * <p>
-     * This helper is the equivalent of:
-     * <pre>
-     * NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
-     * NfcAdapter adapter = manager.getDefaultAdapter();</pre>
-     * @param context the calling application's context
-     *
-     * @return the default NFC adapter, or null if no NFC adapter exists
-     */
-    public static NfcAdapter getDefaultAdapter(Context context) {
-        if (context == null) {
-            throw new IllegalArgumentException("context cannot be null");
-        }
-        context = context.getApplicationContext();
-        if (context == null) {
-            throw new IllegalArgumentException(
-                    "context not associated with any application (using a mock context?)");
-        }
-        retrieveServiceRegisterer();
-        if (sServiceRegisterer.tryGet() == null) {
-            if (sIsInitialized) {
-                synchronized (NfcAdapter.class) {
-                    /* Stale sService pointer */
-                    if (sIsInitialized) sIsInitialized = false;
-                }
-            }
-            return null;
-        }
-        /* Try to initialize the service */
-        NfcManager manager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
-        if (manager == null) {
-            // NFC not available
-            return null;
-        }
-        return manager.getDefaultAdapter();
-    }
-
-    /**
-     * Legacy NfcAdapter getter, always use {@link #getDefaultAdapter(Context)} instead.<p>
-     * This method was deprecated at API level 10 (Gingerbread MR1) because a context is required
-     * for many NFC API methods. Those methods will fail when called on an NfcAdapter
-     * object created from this method.<p>
-     * @deprecated use {@link #getDefaultAdapter(Context)}
-     * @hide
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    public static NfcAdapter getDefaultAdapter() {
-        // introduced in API version 9 (GB 2.3)
-        // deprecated in API version 10 (GB 2.3.3)
-        // removed from public API in version 16 (ICS MR2)
-        // should maintain as a hidden API for binary compatibility for a little longer
-        Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
-                "NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
-
-        return NfcAdapter.getNfcAdapter(null);
-    }
-
-    NfcAdapter(Context context) {
-        mContext = context;
-        mNfcActivityManager = new NfcActivityManager(this);
-        mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>();
-        mTagRemovedListener = null;
-        mLock = new Object();
-        mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService());
-        mNfcWlcStateListener = new NfcWlcStateListener(getService());
-        mNfcVendorNciCallbackListener = new NfcVendorNciCallbackListener(getService());
-        mNfcOemExtension = new NfcOemExtension(mContext, this);
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public Context getContext() {
-        return mContext;
-    }
-
-    /**
-     * Returns the binder interface to the service.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static INfcAdapter getService() {
-        isEnabledStatic();  // NOP call to recover sService if it is stale
-        return sService;
-    }
-
-    /**
-     * Returns the binder interface to the tag service.
-     * @hide
-     */
-    public static INfcTag getTagService() {
-        isEnabledStatic();  // NOP call to recover sTagService if it is stale
-        return sTagService;
-    }
-
-    /**
-     * Returns the binder interface to the card emulation service.
-     * @hide
-     */
-    public static INfcCardEmulation getCardEmulationService() {
-        isEnabledStatic();
-        return sCardEmulationService;
-    }
-
-    /**
-     * Returns the binder interface to the NFC-F card emulation service.
-     * @hide
-     */
-    public static INfcFCardEmulation getNfcFCardEmulationService() {
-        isEnabledStatic();
-        return sNfcFCardEmulationService;
-    }
-
-    /**
-     * Returns the binder interface to the NFC-DTA test interface.
-     * @hide
-     */
-    public INfcDta getNfcDtaInterface() {
-        if (mContext == null) {
-            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
-                    + " NFC extras APIs");
-        }
-        return callServiceReturn(() ->  sService.getNfcDtaInterface(mContext.getPackageName()),
-                null);
-
-    }
-
-    /**
-     * NFC service dead - attempt best effort recovery
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static void attemptDeadServiceRecovery(RemoteException e) {
-        Log.e(TAG, "NFC service dead - attempting to recover", e);
-        INfcAdapter service = getServiceInterface();
-        if (service == null) {
-            Log.e(TAG, "could not retrieve NFC service during service recovery");
-            // nothing more can be done now, sService is still stale, we'll hit
-            // this recovery path again later
-            e.rethrowAsRuntimeException();
-        }
-        // assigning to sService is not thread-safe, but this is best-effort code
-        // and on a well-behaved system should never happen
-        sService = service;
-        if (sHasNfcFeature) {
-            try {
-                sTagService = service.getNfcTagInterface();
-            } catch (RemoteException ee) {
-                sTagService = null;
-                Log.e(TAG, "could not retrieve NFC tag service during service recovery");
-                // nothing more can be done now, sService is still stale, we'll hit
-                // this recovery path again later
-                ee.rethrowAsRuntimeException();
-            }
-        }
-
-        if (sHasCeFeature) {
-            try {
-                sCardEmulationService = service.getNfcCardEmulationInterface();
-            } catch (RemoteException ee) {
-                sCardEmulationService = null;
-                Log.e(TAG,
-                        "could not retrieve NFC card emulation service during service recovery");
-            }
-
-            try {
-                sNfcFCardEmulationService = service.getNfcFCardEmulationInterface();
-            } catch (RemoteException ee) {
-                sNfcFCardEmulationService = null;
-                Log.e(TAG,
-                        "could not retrieve NFC-F card emulation service during service recovery");
-            }
-        }
-    }
-
-    private static boolean isCardEmulationEnabled() {
-        if (sHasCeFeature) {
-            return (sCardEmulationService != null || sNfcFCardEmulationService != null);
-        }
-        return false;
-    }
-
-    private static boolean isTagReadingEnabled() {
-        if (sHasNfcFeature) {
-            return sTagService != null;
-        }
-        return false;
-    }
-
-    private static boolean isEnabledStatic() {
-        boolean serviceState = callServiceReturn(() -> sService.getState() == STATE_ON, false);
-        return serviceState
-                && (isTagReadingEnabled() || isCardEmulationEnabled() || sHasNfcWlcFeature);
-    }
-
-    /**
-     * Return true if this NFC Adapter has any features enabled.
-     *
-     * <p>If this method returns false, the NFC hardware is guaranteed not to
-     * generate or respond to any NFC communication over its NFC radio.
-     * <p>Applications can use this to check if NFC is enabled. Applications
-     * can request Settings UI allowing the user to toggle NFC using:
-     * <p><pre>startActivity(new Intent(Settings.ACTION_NFC_SETTINGS))</pre>
-     *
-     * @see android.provider.Settings#ACTION_NFC_SETTINGS
-     * @return true if this NFC Adapter has any features enabled
-     */
-    public boolean isEnabled() {
-        return isEnabledStatic();
-    }
-
-    /**
-     * Return the state of this NFC Adapter.
-     *
-     * <p>Returns one of {@link #STATE_ON}, {@link #STATE_TURNING_ON},
-     * {@link #STATE_OFF}, {@link #STATE_TURNING_OFF}.
-     *
-     * <p>{@link #isEnabled()} is equivalent to
-     * <code>{@link #getAdapterState()} == {@link #STATE_ON}</code>
-     *
-     * @return the current state of this NFC adapter
-     *
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    public @AdapterState int getAdapterState() {
-        return callServiceReturn(() ->  sService.getState(), NfcAdapter.STATE_OFF);
-
-    }
-
-    /**
-     * Enable NFC hardware.
-     *
-     * <p>This call is asynchronous. Listen for
-     * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
-     * operation is complete.
-     *
-     * <p>This API is only allowed to be called by system apps
-     * or apps which are Device Owner or Profile Owner.
-     *
-     * <p>If this returns true, then either NFC is already on, or
-     * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
-     * to indicate a state transition. If this returns false, then
-     * there is some problem that prevents an attempt to turn
-     * NFC on (for example we are in airplane mode and NFC is not
-     * toggleable in airplane mode on this platform).
-     *
-     */
-    @FlaggedApi(Flags.FLAG_NFC_STATE_CHANGE)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean enable() {
-        return callServiceReturn(() ->  sService.enable(mContext.getPackageName()), false);
-
-    }
-
-    /**
-     * Disable NFC hardware.
-     *
-     * <p>No NFC features will work after this call, and the hardware
-     * will not perform or respond to any NFC communication.
-     *
-     * <p>This call is asynchronous. Listen for
-     * {@link #ACTION_ADAPTER_STATE_CHANGED} broadcasts to find out when the
-     * operation is complete.
-     *
-     * <p>This API is only allowed to be called by system apps
-     * or apps which are Device Owner or Profile Owner.
-     *
-     * <p>If this returns true, then either NFC is already off, or
-     * a {@link #ACTION_ADAPTER_STATE_CHANGED} broadcast will be sent
-     * to indicate a state transition. If this returns false, then
-     * there is some problem that prevents an attempt to turn
-     * NFC off.
-     *
-     */
-    @FlaggedApi(Flags.FLAG_NFC_STATE_CHANGE)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean disable() {
-        return callServiceReturn(() ->  sService.disable(true, mContext.getPackageName()),
-                false);
-
-    }
-
-    /**
-     * Disable NFC hardware.
-     * @hide
-    */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean disable(boolean persist) {
-        return callServiceReturn(() ->  sService.disable(persist, mContext.getPackageName()),
-                false);
-
-    }
-
-    /**
-     * Pauses NFC tag reader mode polling for a {@code timeoutInMs} millisecond.
-     * In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely
-     * use {@link #resumePolling() to resume the polling.
-     * @hide
-     */
-    public void pausePolling(int timeoutInMs) {
-        callService(() -> sService.pausePolling(timeoutInMs));
-    }
-
-
-    /**
-     * Returns whether the device supports observe mode or not. When observe mode is enabled, the
-     * NFC hardware will listen to NFC readers, but not respond to them. While enabled, observed
-     * polling frames will be sent to the APDU service (see {@link #setObserveModeEnabled(boolean)}.
-     * When observe mode is disabled (or if it's not supported), the NFC hardware will automatically
-     * respond to the reader and proceed with the transaction.
-     * @return true if the mode is supported, false otherwise.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
-    public boolean isObserveModeSupported() {
-        return callServiceReturn(() ->  sService.isObserveModeSupported(), false);
-    }
-
-    /**
-     * Returns whether Observe Mode is currently enabled or not.
-     *
-     * @return true if observe mode is enabled, false otherwise.
-     */
-
-    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
-    public boolean isObserveModeEnabled() {
-        return callServiceReturn(() ->  sService.isObserveModeEnabled(), false);
-    }
-
-    /**
-     * Controls whether the NFC adapter will allow transactions to proceed or be in observe mode
-     * and simply observe and notify the APDU service of polling loop frames. See
-     * {@link #isObserveModeSupported()} for a description of observe mode. Only the package of the
-     * currently preferred service (the service set as preferred by the current foreground
-     * application via {@link android.nfc.cardemulation.CardEmulation#setPreferredService(Activity,
-     * android.content.ComponentName)} or the current Default Wallet Role Holder
-     * {@link android.app.role.RoleManager#ROLE_WALLET}), otherwise a call to this method will fail
-     * and return false.
-     *
-     * @param enabled false disables observe mode to allow the transaction to proceed while true
-     *                enables observe mode and does not allow transactions to proceed.
-     *
-     * @return boolean indicating success or failure.
-     */
-
-    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
-    public boolean setObserveModeEnabled(boolean enabled) {
-        if (mContext == null) {
-            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
-                    + " observe mode APIs");
-        }
-        return callServiceReturn(() ->  sService.setObserveMode(enabled, mContext.getPackageName()),
-                false);
-    }
-
-    /**
-     * Resumes default NFC tag reader mode polling for the current device state if polling is
-     * paused. Calling this while already in polling is a no-op.
-     * @hide
-     */
-    public void resumePolling() {
-        callService(() -> sService.resumePolling());
-    }
-
-    /**
-     * Set one or more {@link Uri}s to send using Android Beam (TM). Every
-     * Uri you provide must have either scheme 'file' or scheme 'content'.
-     *
-     * <p>For the data provided through this method, Android Beam tries to
-     * switch to alternate transports such as Bluetooth to achieve a fast
-     * transfer speed. Hence this method is very suitable
-     * for transferring large files such as pictures or songs.
-     *
-     * <p>The receiving side will store the content of each Uri in
-     * a file and present a notification to the user to open the file
-     * with a {@link android.content.Intent} with action
-     * {@link android.content.Intent#ACTION_VIEW}.
-     * If multiple URIs are sent, the {@link android.content.Intent} will refer
-     * to the first of the stored files.
-     *
-     * <p>This method may be called at any time before {@link Activity#onDestroy},
-     * but the URI(s) are only made available for Android Beam when the
-     * specified activity(s) are in resumed (foreground) state. The recommended
-     * approach is to call this method during your Activity's
-     * {@link Activity#onCreate} - see sample
-     * code below. This method does not immediately perform any I/O or blocking work,
-     * so is safe to call on your main thread.
-     *
-     * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
-     * have priority over both {@link #setNdefPushMessage} and
-     * {@link #setNdefPushMessageCallback}.
-     *
-     * <p>If {@link #setBeamPushUris} is called with a null Uri array,
-     * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
-     * then the Uri push will be completely disabled for the specified activity(s).
-     *
-     * <p>Code example:
-     * <pre>
-     * protected void onCreate(Bundle savedInstanceState) {
-     *     super.onCreate(savedInstanceState);
-     *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
-     *     if (nfcAdapter == null) return;  // NFC not available on this device
-     *     nfcAdapter.setBeamPushUris(new Uri[] {uri1, uri2}, this);
-     * }</pre>
-     * And that is it. Only one call per activity is necessary. The Android
-     * OS will automatically release its references to the Uri(s) and the
-     * Activity object when it is destroyed if you follow this pattern.
-     *
-     * <p>If your Activity wants to dynamically supply Uri(s),
-     * then set a callback using {@link #setBeamPushUrisCallback} instead
-     * of using this method.
-     *
-     * <p class="note">Do not pass in an Activity that has already been through
-     * {@link Activity#onDestroy}. This is guaranteed if you call this API
-     * during {@link Activity#onCreate}.
-     *
-     * <p class="note">If this device does not support alternate transports
-     * such as Bluetooth or WiFI, calling this method does nothing.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param uris an array of Uri(s) to push over Android Beam
-     * @param activity activity for which the Uri(s) will be pushed
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public void setBeamPushUris(Uri[] uris, Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Set a callback that will dynamically generate one or more {@link Uri}s
-     * to send using Android Beam (TM). Every Uri the callback provides
-     * must have either scheme 'file' or scheme 'content'.
-     *
-     * <p>For the data provided through this callback, Android Beam tries to
-     * switch to alternate transports such as Bluetooth to achieve a fast
-     * transfer speed. Hence this method is very suitable
-     * for transferring large files such as pictures or songs.
-     *
-     * <p>The receiving side will store the content of each Uri in
-     * a file and present a notification to the user to open the file
-     * with a {@link android.content.Intent} with action
-     * {@link android.content.Intent#ACTION_VIEW}.
-     * If multiple URIs are sent, the {@link android.content.Intent} will refer
-     * to the first of the stored files.
-     *
-     * <p>This method may be called at any time before {@link Activity#onDestroy},
-     * but the URI(s) are only made available for Android Beam when the
-     * specified activity(s) are in resumed (foreground) state. The recommended
-     * approach is to call this method during your Activity's
-     * {@link Activity#onCreate} - see sample
-     * code below. This method does not immediately perform any I/O or blocking work,
-     * so is safe to call on your main thread.
-     *
-     * <p>{@link #setBeamPushUris} and {@link #setBeamPushUrisCallback}
-     * have priority over both {@link #setNdefPushMessage} and
-     * {@link #setNdefPushMessageCallback}.
-     *
-     * <p>If {@link #setBeamPushUris} is called with a null Uri array,
-     * and/or {@link #setBeamPushUrisCallback} is called with a null callback,
-     * then the Uri push will be completely disabled for the specified activity(s).
-     *
-     * <p>Code example:
-     * <pre>
-     * protected void onCreate(Bundle savedInstanceState) {
-     *     super.onCreate(savedInstanceState);
-     *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
-     *     if (nfcAdapter == null) return;  // NFC not available on this device
-     *     nfcAdapter.setBeamPushUrisCallback(callback, this);
-     * }</pre>
-     * And that is it. Only one call per activity is necessary. The Android
-     * OS will automatically release its references to the Uri(s) and the
-     * Activity object when it is destroyed if you follow this pattern.
-     *
-     * <p class="note">Do not pass in an Activity that has already been through
-     * {@link Activity#onDestroy}. This is guaranteed if you call this API
-     * during {@link Activity#onCreate}.
-     *
-     * <p class="note">If this device does not support alternate transports
-     * such as Bluetooth or WiFI, calling this method does nothing.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param callback callback, or null to disable
-     * @param activity activity for which the Uri(s) will be pushed
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public void setBeamPushUrisCallback(CreateBeamUrisCallback callback, Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Set a static {@link NdefMessage} to send using Android Beam (TM).
-     *
-     * <p>This method may be called at any time before {@link Activity#onDestroy},
-     * but the NDEF message is only made available for NDEF push when the
-     * specified activity(s) are in resumed (foreground) state. The recommended
-     * approach is to call this method during your Activity's
-     * {@link Activity#onCreate} - see sample
-     * code below. This method does not immediately perform any I/O or blocking work,
-     * so is safe to call on your main thread.
-     *
-     * <p>Only one NDEF message can be pushed by the currently resumed activity.
-     * If both {@link #setNdefPushMessage} and
-     * {@link #setNdefPushMessageCallback} are set, then
-     * the callback will take priority.
-     *
-     * <p>If neither {@link #setNdefPushMessage} or
-     * {@link #setNdefPushMessageCallback} have been called for your activity, then
-     * the Android OS may choose to send a default NDEF message on your behalf,
-     * such as a URI for your application.
-     *
-     * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
-     * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
-     * then NDEF push will be completely disabled for the specified activity(s).
-     * This also disables any default NDEF message the Android OS would have
-     * otherwise sent on your behalf for those activity(s).
-     *
-     * <p>If you want to prevent the Android OS from sending default NDEF
-     * messages completely (for all activities), you can include a
-     * {@code <meta-data>} element inside the {@code <application>}
-     * element of your AndroidManifest.xml file, like this:
-     * <pre>
-     * &lt;application ...>
-     *     &lt;meta-data android:name="android.nfc.disable_beam_default"
-     *         android:value="true" />
-     * &lt;/application></pre>
-     *
-     * <p>The API allows for multiple activities to be specified at a time,
-     * but it is strongly recommended to just register one at a time,
-     * and to do so during the activity's {@link Activity#onCreate}. For example:
-     * <pre>
-     * protected void onCreate(Bundle savedInstanceState) {
-     *     super.onCreate(savedInstanceState);
-     *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
-     *     if (nfcAdapter == null) return;  // NFC not available on this device
-     *     nfcAdapter.setNdefPushMessage(ndefMessage, this);
-     * }</pre>
-     * And that is it. Only one call per activity is necessary. The Android
-     * OS will automatically release its references to the NDEF message and the
-     * Activity object when it is destroyed if you follow this pattern.
-     *
-     * <p>If your Activity wants to dynamically generate an NDEF message,
-     * then set a callback using {@link #setNdefPushMessageCallback} instead
-     * of a static message.
-     *
-     * <p class="note">Do not pass in an Activity that has already been through
-     * {@link Activity#onDestroy}. This is guaranteed if you call this API
-     * during {@link Activity#onCreate}.
-     *
-     * <p class="note">For sending large content such as pictures and songs,
-     * consider using {@link #setBeamPushUris}, which switches to alternate transports
-     * such as Bluetooth to achieve a fast transfer rate.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param message NDEF message to push over NFC, or null to disable
-     * @param activity activity for which the NDEF message will be pushed
-     * @param activities optional additional activities, however we strongly recommend
-     *        to only register one at a time, and to do so in that activity's
-     *        {@link Activity#onCreate}
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public void setNdefPushMessage(NdefMessage message, Activity activity,
-            Activity ... activities) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * @hide
-     * @removed
-     */
-    @SystemApi
-    @UnsupportedAppUsage
-    public void setNdefPushMessage(NdefMessage message, Activity activity, int flags) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Set a callback that dynamically generates NDEF messages to send using Android Beam (TM).
-     *
-     * <p>This method may be called at any time before {@link Activity#onDestroy},
-     * but the NDEF message callback can only occur when the
-     * specified activity(s) are in resumed (foreground) state. The recommended
-     * approach is to call this method during your Activity's
-     * {@link Activity#onCreate} - see sample
-     * code below. This method does not immediately perform any I/O or blocking work,
-     * so is safe to call on your main thread.
-     *
-     * <p>Only one NDEF message can be pushed by the currently resumed activity.
-     * If both {@link #setNdefPushMessage} and
-     * {@link #setNdefPushMessageCallback} are set, then
-     * the callback will take priority.
-     *
-     * <p>If neither {@link #setNdefPushMessage} or
-     * {@link #setNdefPushMessageCallback} have been called for your activity, then
-     * the Android OS may choose to send a default NDEF message on your behalf,
-     * such as a URI for your application.
-     *
-     * <p>If {@link #setNdefPushMessage} is called with a null NDEF message,
-     * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
-     * then NDEF push will be completely disabled for the specified activity(s).
-     * This also disables any default NDEF message the Android OS would have
-     * otherwise sent on your behalf for those activity(s).
-     *
-     * <p>If you want to prevent the Android OS from sending default NDEF
-     * messages completely (for all activities), you can include a
-     * {@code <meta-data>} element inside the {@code <application>}
-     * element of your AndroidManifest.xml file, like this:
-     * <pre>
-     * &lt;application ...>
-     *     &lt;meta-data android:name="android.nfc.disable_beam_default"
-     *         android:value="true" />
-     * &lt;/application></pre>
-     *
-     * <p>The API allows for multiple activities to be specified at a time,
-     * but it is strongly recommended to just register one at a time,
-     * and to do so during the activity's {@link Activity#onCreate}. For example:
-     * <pre>
-     * protected void onCreate(Bundle savedInstanceState) {
-     *     super.onCreate(savedInstanceState);
-     *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
-     *     if (nfcAdapter == null) return;  // NFC not available on this device
-     *     nfcAdapter.setNdefPushMessageCallback(callback, this);
-     * }</pre>
-     * And that is it. Only one call per activity is necessary. The Android
-     * OS will automatically release its references to the callback and the
-     * Activity object when it is destroyed if you follow this pattern.
-     *
-     * <p class="note">Do not pass in an Activity that has already been through
-     * {@link Activity#onDestroy}. This is guaranteed if you call this API
-     * during {@link Activity#onCreate}.
-     * <p class="note">For sending large content such as pictures and songs,
-     * consider using {@link #setBeamPushUris}, which switches to alternate transports
-     * such as Bluetooth to achieve a fast transfer rate.
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param callback callback, or null to disable
-     * @param activity activity for which the NDEF message will be pushed
-     * @param activities optional additional activities, however we strongly recommend
-     *        to only register one at a time, and to do so in that activity's
-     *        {@link Activity#onCreate}
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
-            Activity ... activities) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Set a callback on successful Android Beam (TM).
-     *
-     * <p>This method may be called at any time before {@link Activity#onDestroy},
-     * but the callback can only occur when the
-     * specified activity(s) are in resumed (foreground) state. The recommended
-     * approach is to call this method during your Activity's
-     * {@link Activity#onCreate} - see sample
-     * code below. This method does not immediately perform any I/O or blocking work,
-     * so is safe to call on your main thread.
-     *
-     * <p>The API allows for multiple activities to be specified at a time,
-     * but it is strongly recommended to just register one at a time,
-     * and to do so during the activity's {@link Activity#onCreate}. For example:
-     * <pre>
-     * protected void onCreate(Bundle savedInstanceState) {
-     *     super.onCreate(savedInstanceState);
-     *     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
-     *     if (nfcAdapter == null) return;  // NFC not available on this device
-     *     nfcAdapter.setOnNdefPushCompleteCallback(callback, this);
-     * }</pre>
-     * And that is it. Only one call per activity is necessary. The Android
-     * OS will automatically release its references to the callback and the
-     * Activity object when it is destroyed if you follow this pattern.
-     *
-     * <p class="note">Do not pass in an Activity that has already been through
-     * {@link Activity#onDestroy}. This is guaranteed if you call this API
-     * during {@link Activity#onCreate}.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param callback callback, or null to disable
-     * @param activity activity for which the NDEF message will be pushed
-     * @param activities optional additional activities, however we strongly recommend
-     *        to only register one at a time, and to do so in that activity's
-     *        {@link Activity#onCreate}
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
-            Activity activity, Activity ... activities) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Enable foreground dispatch to the given Activity.
-     *
-     * <p>This will give priority to the foreground activity when
-     * dispatching a discovered {@link Tag} to an application.
-     *
-     * <p>If any IntentFilters are provided to this method they are used to match dispatch Intents
-     * for both the {@link NfcAdapter#ACTION_NDEF_DISCOVERED} and
-     * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. Since {@link NfcAdapter#ACTION_TECH_DISCOVERED}
-     * relies on meta data outside of the IntentFilter matching for that dispatch Intent is handled
-     * by passing in the tech lists separately. Each first level entry in the tech list represents
-     * an array of technologies that must all be present to match. If any of the first level sets
-     * match then the dispatch is routed through the given PendingIntent. In other words, the second
-     * level is ANDed together and the first level entries are ORed together.
-     *
-     * <p>If you pass {@code null} for both the {@code filters} and {@code techLists} parameters
-     * that acts a wild card and will cause the foreground activity to receive all tags via the
-     * {@link NfcAdapter#ACTION_TAG_DISCOVERED} intent.
-     *
-     * <p>This method must be called from the main thread, and only when the activity is in the
-     * foreground (resumed). Also, activities must call {@link #disableForegroundDispatch} before
-     * the completion of their {@link Activity#onPause} callback to disable foreground dispatch
-     * after it has been enabled.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param activity the Activity to dispatch to
-     * @param intent the PendingIntent to start for the dispatch
-     * @param filters the IntentFilters to override dispatching for, or null to always dispatch
-     * @param techLists the tech lists used to perform matching for dispatching of the
-     *      {@link NfcAdapter#ACTION_TECH_DISCOVERED} intent
-     * @throws IllegalStateException if the Activity is not currently in the foreground
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    public void enableForegroundDispatch(Activity activity, PendingIntent intent,
-            IntentFilter[] filters, String[][] techLists) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        if (activity == null || intent == null) {
-            throw new NullPointerException();
-        }
-        final TechListParcel parcel = (techLists != null && techLists.length > 0)
-            ? new TechListParcel(techLists)
-            : null;
-        callService(() -> sService.setForegroundDispatch(intent, filters, parcel));
-    }
-
-    /**
-     * Disable foreground dispatch to the given activity.
-     *
-     * <p>After calling {@link #enableForegroundDispatch}, an activity
-     * must call this method before its {@link Activity#onPause} callback
-     * completes.
-     *
-     * <p>This method must be called from the main thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param activity the Activity to disable dispatch to
-     * @throws IllegalStateException if the Activity has already been paused
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    public void disableForegroundDispatch(Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        callService(() -> sService.setForegroundDispatch(null, null, null));
-    }
-
-    /**
-     * Limit the NFC controller to reader mode while this Activity is in the foreground.
-     *
-     * <p>In this mode the NFC controller will only act as an NFC tag reader/writer,
-     * thus disabling any peer-to-peer (Android Beam) and card-emulation modes of
-     * the NFC adapter on this device.
-     *
-     * <p>Use {@link #FLAG_READER_SKIP_NDEF_CHECK} to prevent the platform from
-     * performing any NDEF checks in reader mode. Note that this will prevent the
-     * {@link Ndef} tag technology from being enumerated on the tag, and that
-     * NDEF-based tag dispatch will not be functional.
-     *
-     * <p>For interacting with tags that are emulated on another Android device
-     * using Android's host-based card-emulation, the recommended flags are
-     * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}.
-     *
-     * @param activity the Activity that requests the adapter to be in reader mode
-     * @param callback the callback to be called when a tag is discovered
-     * @param flags Flags indicating poll technologies and other optional parameters
-     * @param extras Additional extras for configuring reader mode.
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
-            Bundle extras) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        mNfcActivityManager.enableReaderMode(activity, callback, flags, extras);
-    }
-
-    /**
-     * Restore the NFC adapter to normal mode of operation: supporting
-     * peer-to-peer (Android Beam), card emulation, and polling for
-     * all supported tag technologies.
-     *
-     * @param activity the Activity that currently has reader mode enabled
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    public void disableReaderMode(Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        mNfcActivityManager.disableReaderMode(activity);
-    }
-
-    // Flags arguments to NFC adapter to enable/disable NFC
-    private static final int DISABLE_POLLING_FLAGS = 0x1000;
-    private static final int ENABLE_POLLING_FLAGS = 0x0000;
-
-    /**
-     * Privileged API to enable or disable reader polling.
-     * Unlike {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}, this API does not
-     * need a foreground activity to control reader mode parameters
-     * Note: Use with caution! The app is responsible for ensuring that the polling state is
-     * returned to normal.
-     *
-     * @see #enableReaderMode(Activity, ReaderCallback, int, Bundle)  for more detailed
-     * documentation.
-     *
-     * @param enablePolling whether to enable or disable polling.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    @SuppressLint("VisiblySynchronized")
-    public void setReaderModePollingEnabled(boolean enable) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        Binder token = new Binder();
-        int flags = enable ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS;
-        callService(() -> sService.setReaderMode(
-                token, null, flags, null, mContext.getPackageName()));
-    }
-
-    /**
-     * Set the NFC controller to enable specific poll/listen technologies,
-     * as specified in parameters, while this Activity is in the foreground.
-     *
-     * Use {@link #FLAG_READER_KEEP} to keep current polling technology.
-     * Use {@link #FLAG_LISTEN_KEEP} to keep current listenig technology.
-     * (if the _KEEP flag is specified the other technology flags shouldn't be set
-     * and are quietly ignored otherwise).
-     * Use {@link #FLAG_READER_DISABLE} to disable polling.
-     * Use {@link #FLAG_LISTEN_DISABLE} to disable listening.
-     * Also refer to {@link #resetDiscoveryTechnology(Activity)} to restore these changes.
-     * </p>
-     * The pollTechnology, listenTechnology parameters can be one or several of below list.
-     * <pre>
-     *                    Poll                    Listen
-     *  Passive A         0x01   (NFC_A)           0x01  (NFC_PASSIVE_A)
-     *  Passive B         0x02   (NFC_B)           0x02  (NFC_PASSIVE_B)
-     *  Passive F         0x04   (NFC_F)           0x04  (NFC_PASSIVE_F)
-     *  ISO 15693         0x08   (NFC_V)             -
-     *  Kovio             0x10   (NFC_BARCODE)       -
-     * </pre>
-     * <p>Example usage in an Activity that requires to disable poll,
-     * keep current listen technologies:
-     * <pre>
-     * protected void onResume() {
-     *     mNfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
-     *     mNfcAdapter.setDiscoveryTechnology(this,
-     *         NfcAdapter.FLAG_READER_DISABLE, NfcAdapter.FLAG_LISTEN_KEEP);
-     * }</pre></p>
-     * @param activity The Activity that requests NFC controller to enable specific technologies.
-     * @param pollTechnology Flags indicating poll technologies.
-     * @param listenTechnology Flags indicating listen technologies.
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable.
-     *
-     * NOTE: This API overrides all technology flags regardless of the current device state,
-     *       it is incompatible with enableReaderMode() API and the others that either update
-     *       or assume any techlology flag set by the OS.
-     *       Please use with care.
-     */
-
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public void setDiscoveryTechnology(@NonNull Activity activity,
-            @PollTechnology int pollTechnology, @ListenTechnology int listenTechnology) {
-
-        if (listenTechnology == FLAG_LISTEN_DISABLE) {
-            synchronized (sLock) {
-                if (!sHasNfcFeature) {
-                    throw new UnsupportedOperationException();
-                }
-            }
-        } else if (pollTechnology == FLAG_READER_DISABLE) {
-            synchronized (sLock) {
-                if (!sHasCeFeature) {
-                    throw new UnsupportedOperationException();
-                }
-            }
-        } else {
-            synchronized (sLock) {
-                if (!sHasNfcFeature || !sHasCeFeature) {
-                    throw new UnsupportedOperationException();
-                }
-            }
-        }
-    /*
-     * Privileged FLAG to set technology mask for all data processed by NFC controller
-     * Note: Use with caution! The app is responsible for ensuring that the discovery
-     * technology mask is returned to default.
-     * Note: FLAG_USE_ALL_TECH used with _KEEP flags will reset the technolody to android default
-     */
-        if (Flags.nfcSetDefaultDiscTech()
-                && ((pollTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH
-                || (listenTechnology & FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) {
-            Binder token = new Binder();
-            callService( () ->
-                    sService.updateDiscoveryTechnology(
-                            token, pollTechnology, listenTechnology, mContext.getPackageName()));
-        } else {
-            mNfcActivityManager.setDiscoveryTech(activity, pollTechnology, listenTechnology);
-        }
-    }
-
-    /**
-     * Restore the poll/listen technologies of NFC controller to its default state,
-     * which were changed by {@link #setDiscoveryTechnology(Activity , int , int)}
-     *
-     * @param activity The Activity that requested to change technologies.
-     */
-
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
-    public void resetDiscoveryTechnology(@NonNull Activity activity) {
-        mNfcActivityManager.resetDiscoveryTech(activity);
-    }
-
-    /**
-     * Manually invoke Android Beam to share data.
-     *
-     * <p>The Android Beam animation is normally only shown when two NFC-capable
-     * devices come into range.
-     * By calling this method, an Activity can invoke the Beam animation directly
-     * even if no other NFC device is in range yet. The Beam animation will then
-     * prompt the user to tap another NFC-capable device to complete the data
-     * transfer.
-     *
-     * <p>The main advantage of using this method is that it avoids the need for the
-     * user to tap the screen to complete the transfer, as this method already
-     * establishes the direction of the transfer and the consent of the user to
-     * share data. Callers are responsible for making sure that the user has
-     * consented to sharing data on NFC tap.
-     *
-     * <p>Note that to use this method, the passed in Activity must have already
-     * set data to share over Beam by using method calls such as
-     * {@link #setNdefPushMessageCallback} or
-     * {@link #setBeamPushUrisCallback}.
-     *
-     * @param activity the current foreground Activity that has registered data to share
-     * @return whether the Beam animation was successfully invoked
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public boolean invokeBeam(Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Enable NDEF message push over NFC while this Activity is in the foreground.
-     *
-     * <p>You must explicitly call this method every time the activity is
-     * resumed, and you must call {@link #disableForegroundNdefPush} before
-     * your activity completes {@link Activity#onPause}.
-     *
-     * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
-     * instead: it automatically hooks into your activity life-cycle,
-     * so you do not need to call enable/disable in your onResume/onPause.
-     *
-     * <p>For NDEF push to function properly the other NFC device must
-     * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or
-     * Android's "com.android.npp" (Ndef Push Protocol). This was optional
-     * on Gingerbread level Android NFC devices, but SNEP is mandatory on
-     * Ice-Cream-Sandwich and beyond.
-     *
-     * <p>This method must be called from the main thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param activity foreground activity
-     * @param message a NDEF Message to push over NFC
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Disable NDEF message push over P2P.
-     *
-     * <p>After calling {@link #enableForegroundNdefPush}, an activity
-     * must call this method before its {@link Activity#onPause} callback
-     * completes.
-     *
-     * <p>Strongly recommend to use the new {@link #setNdefPushMessage}
-     * instead: it automatically hooks into your activity life-cycle,
-     * so you do not need to call enable/disable in your onResume/onPause.
-     *
-     * <p>This method must be called from the main thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param activity the Foreground activity
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @Deprecated
-    @UnsupportedAppUsage
-    public void disableForegroundNdefPush(Activity activity) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
-    /**
-     * Sets Secure NFC feature.
-     * <p>This API is for the Settings application.
-     * @return True if successful
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean enableSecureNfc(boolean enable) {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.setNfcSecure(enable), false);
-
-    }
-
-    /**
-     * Checks if the device supports Secure NFC functionality.
-     *
-     * @return True if device supports Secure NFC, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     */
-    public boolean isSecureNfcSupported() {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.deviceSupportsNfcSecure(), false);
-
-    }
-
-    /**
-     * Returns information regarding Nfc antennas on the device
-     * such as their relative positioning on the device.
-     *
-     * @return Information on the nfc antenna(s) on the device.
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     */
-    @Nullable
-    public NfcAntennaInfo getNfcAntennaInfo() {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.getNfcAntennaInfo(), null);
-
-    }
-
-    /**
-     * Checks Secure NFC feature is enabled.
-     *
-     * @return True if Secure NFC is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     * @throws UnsupportedOperationException if device doesn't support
-     *         Secure NFC functionality. {@link #isSecureNfcSupported}
-     */
-    public boolean isSecureNfcEnabled() {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isNfcSecureEnabled(), false);
-
-    }
-
-    /**
-     * Sets NFC Reader option feature.
-     * <p>This API is for the Settings application.
-     * @return True if successful
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean enableReaderOption(boolean enable) {
-        if (!sHasNfcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->
-                sService.enableReaderOption(enable, mContext.getPackageName()), false);
-
-    }
-
-    /**
-     * Checks if the device supports NFC Reader option functionality.
-     *
-     * @return True if device supports NFC Reader option, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
-    public boolean isReaderOptionSupported() {
-        if (!sHasNfcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isReaderOptionSupported(), false);
-
-    }
-
-    /**
-     * Checks NFC Reader option feature is enabled.
-     *
-     * @return True if NFC Reader option  is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @throws UnsupportedOperationException if device doesn't support
-     *         NFC Reader option functionality. {@link #isReaderOptionSupported}
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_READER_OPTION)
-    public boolean isReaderOptionEnabled() {
-        if (!sHasNfcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isReaderOptionEnabled(), false);
-
-    }
-
-    /**
-     * Enable NDEF Push feature.
-     * <p>This API is for the Settings application.
-     * @hide
-     * @removed
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @UnsupportedAppUsage
-    public boolean enableNdefPush() {
-        return false;
-    }
-
-    /**
-     * Disable NDEF Push feature.
-     * <p>This API is for the Settings application.
-     * @hide
-     * @removed
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @UnsupportedAppUsage
-    public boolean disableNdefPush() {
-        return false;
-    }
-
-    /**
-     * Return true if the NDEF Push (Android Beam) feature is enabled.
-     * <p>This function will return true only if both NFC is enabled, and the
-     * NDEF Push feature is enabled.
-     * <p>Note that if NFC is enabled but NDEF Push is disabled then this
-     * device can still <i>receive</i> NDEF messages, it just cannot send them.
-     * <p>Applications cannot directly toggle the NDEF Push feature, but they
-     * can request Settings UI allowing the user to toggle NDEF Push using
-     * <code>startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS))</code>
-     * <p>Example usage in an Activity that requires NDEF Push:
-     * <p><pre>
-     * protected void onResume() {
-     *     super.onResume();
-     *     if (!nfcAdapter.isEnabled()) {
-     *         startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
-     *     } else if (!nfcAdapter.isNdefPushEnabled()) {
-     *         startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
-     *     }
-     * }</pre>
-     *
-     * @see android.provider.Settings#ACTION_NFCSHARING_SETTINGS
-     * @return true if NDEF Push feature is enabled
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     * @removed this feature is removed. File sharing can work using other technology like
-     * Bluetooth.
-     */
-    @java.lang.Deprecated
-    @UnsupportedAppUsage
-    public boolean isNdefPushEnabled() {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Signals that you are no longer interested in communicating with an NFC tag
-     * for as long as it remains in range.
-     *
-     * All future attempted communication to this tag will fail with {@link IOException}.
-     * The NFC controller will be put in a low-power polling mode, allowing the device
-     * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in
-     * car dock).
-     *
-     * Additionally the debounceMs parameter allows you to specify for how long the tag needs
-     * to have gone out of range, before it will be dispatched again.
-     *
-     * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms).
-     * This means that if the tag repeatedly goes in and out of range (for example, in
-     * case of a flaky connection), and the controller happens to poll every time the
-     * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag
-     * having been "in range" during the interval.
-     *
-     * Note 2: if a tag with another UID is detected after this API is called, its effect
-     * will be cancelled; if this tag shows up before the amount of time specified in
-     * debounceMs, it will be dispatched again.
-     *
-     * Note 3: some tags have a random UID, in which case this API won't work reliably.
-     *
-     * @param tag        the {@link android.nfc.Tag Tag} to ignore.
-     * @param debounceMs minimum amount of time the tag needs to be out of range before being
-     *                   dispatched again.
-     * @param tagRemovedListener listener to be called when the tag is removed from the field.
-     *                           Note that this will only be called if the tag has been out of range
-     *                           for at least debounceMs, or if another tag came into range before
-     *                           debounceMs. May be null in case you don't want a callback.
-     * @param handler the {@link android.os.Handler Handler} that will be used for delivering
-     *                the callback. if the handler is null, then the thread used for delivering
-     *                the callback is unspecified.
-     * @return false if the tag couldn't be found (or has already gone out of range), true otherwise
-     */
-    public boolean ignore(final Tag tag, int debounceMs,
-                          final OnTagRemovedListener tagRemovedListener, final Handler handler) {
-        ITagRemovedCallback.Stub iListener = null;
-        if (tagRemovedListener != null) {
-            iListener = new ITagRemovedCallback.Stub() {
-                @Override
-                public void onTagRemoved() throws RemoteException {
-                    if (handler != null) {
-                        handler.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                tagRemovedListener.onTagRemoved();
-                            }
-                        });
-                    } else {
-                        tagRemovedListener.onTagRemoved();
-                    }
-                    synchronized (mLock) {
-                        mTagRemovedListener = null;
-                    }
-                }
-            };
-        }
-        synchronized (mLock) {
-            mTagRemovedListener = iListener;
-        }
-        final ITagRemovedCallback.Stub passedListener = iListener;
-        return callServiceReturn(() ->
-                sService.ignore(tag.getServiceHandle(), debounceMs, passedListener), false);
-    }
-
-    /**
-     * Inject a mock NFC tag.<p>
-     * Used for testing purposes.
-     * <p class="note">Requires the
-     * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission.
-     * @hide
-     */
-    public void dispatch(Tag tag) {
-        if (tag == null) {
-            throw new NullPointerException("tag cannot be null");
-        }
-        callService(() -> sService.dispatch(tag));
-    }
-
-    /**
-     * Registers a new NFC unlock handler with the NFC service.
-     *
-     * <p />NFC unlock handlers are intended to unlock the keyguard in the presence of a trusted
-     * NFC device. The handler should return true if it successfully authenticates the user and
-     * unlocks the keyguard.
-     *
-     * <p /> The parameter {@code tagTechnologies} determines which Tag technologies will be polled for
-     * at the lockscreen. Polling for less tag technologies reduces latency, and so it is
-     * strongly recommended to only provide the Tag technologies that the handler is expected to
-     * receive. There must be at least one tag technology provided, otherwise the unlock handler
-     * is ignored.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
-                                       String[] tagTechnologies) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        // If there are no tag technologies, don't bother adding unlock handler
-        if (tagTechnologies.length == 0) {
-            return false;
-        }
-
-        try {
-            synchronized (mLock) {
-                if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
-                    // update the tag technologies
-                    callService(() -> {
-                        sService.removeNfcUnlockHandler(mNfcUnlockHandlers.get(unlockHandler));
-                        mNfcUnlockHandlers.remove(unlockHandler);
-                    });
-                }
-
-                INfcUnlockHandler.Stub iHandler = new INfcUnlockHandler.Stub() {
-                    @Override
-                    public boolean onUnlockAttempted(Tag tag) throws RemoteException {
-                        return unlockHandler.onUnlockAttempted(tag);
-                    }
-                };
-                return callServiceReturn(() -> {
-                        sService.addNfcUnlockHandler(
-                            iHandler, Tag.getTechCodesFromStrings(tagTechnologies));
-                        mNfcUnlockHandlers.put(unlockHandler, iHandler);
-                        return true;
-                    }, false);
-            }
-        } catch (IllegalArgumentException e) {
-            Log.e(TAG, "Unable to register LockscreenDispatch", e);
-            return false;
-        }
-
-    }
-
-    /**
-     * Removes a previously registered unlock handler. Also removes the tag technologies
-     * associated with the removed unlock handler.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        synchronized (mLock) {
-            if (mNfcUnlockHandlers.containsKey(unlockHandler)) {
-                return callServiceReturn(() -> {
-                    sService.removeNfcUnlockHandler(mNfcUnlockHandlers.remove(unlockHandler));
-                    return true;
-                }, false);
-            }
-            return true;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    public INfcAdapterExtras getNfcAdapterExtrasInterface() {
-        if (mContext == null) {
-            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
-                    + " NFC extras APIs");
-        }
-        return callServiceReturn(() ->
-                sService.getNfcAdapterExtrasInterface(mContext.getPackageName()), null);
-
-    }
-
-    void enforceResumed(Activity activity) {
-        if (!activity.isResumed()) {
-            throw new IllegalStateException("API cannot be called while activity is paused");
-        }
-    }
-
-    int getSdkVersion() {
-        if (mContext == null) {
-            return android.os.Build.VERSION_CODES.GINGERBREAD; // best guess
-        } else {
-            return mContext.getApplicationInfo().targetSdkVersion;
-        }
-    }
-
-    /**
-     * Sets NFC controller always on feature.
-     * <p>This API is for the NFCC internal state management. It allows to discriminate
-     * the controller function from the NFC function by keeping the NFC controller on without
-     * any NFC RF enabled if necessary.
-     * <p>This call is asynchronous. Register a listener {@link ControllerAlwaysOnListener}
-     * by {@link #registerControllerAlwaysOnListener} to find out when the operation is
-     * complete.
-     * <p>If this returns true, then either NFCC always on state has been set based on the value,
-     * or a {@link ControllerAlwaysOnListener#onControllerAlwaysOnChanged(boolean)} will be invoked
-     * to indicate the state change.
-     * If this returns false, then there is some problem that prevents an attempt to turn NFCC
-     * always on.
-     * @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is
-     * disabled), if false the NFCC will follow completely the Nfc adapter state.
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     * @return true if feature is supported by the device and operation has been initiated,
-     * false if the feature is not supported by the device.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public boolean setControllerAlwaysOn(boolean value) {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        int mode = value ? CONTROLLER_ALWAYS_ON_MODE_DEFAULT : CONTROLLER_ALWAYS_ON_DISABLE;
-        try {
-            callService(() -> sService.setControllerAlwaysOn(mode));
-        } catch (UnsupportedOperationException e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Checks NFC controller always on feature is enabled.
-     *
-     * @return True if NFC controller always on is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public boolean isControllerAlwaysOn() {
-        return callServiceReturn(() ->  sService.isControllerAlwaysOn(), false);
-
-    }
-
-    /**
-     * Checks if the device supports NFC controller always on functionality.
-     *
-     * @return True if device supports NFC controller always on, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC,
-     * FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     * FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     * are unavailable
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public boolean isControllerAlwaysOnSupported() {
-        if (!sHasNfcFeature && !sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isControllerAlwaysOnSupported(), false);
-
-    }
-
-    /**
-     * Register a {@link ControllerAlwaysOnListener} to listen for NFC controller always on
-     * state changes
-     * <p>The provided listener will be invoked by the given {@link Executor}.
-     *
-     * @param executor an {@link Executor} to execute given listener
-     * @param listener user implementation of the {@link ControllerAlwaysOnListener}
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public void registerControllerAlwaysOnListener(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull ControllerAlwaysOnListener listener) {
-        mControllerAlwaysOnListener.register(executor, listener);
-    }
-
-    /**
-     * Unregister the specified {@link ControllerAlwaysOnListener}
-     * <p>The same {@link ControllerAlwaysOnListener} object used when calling
-     * {@link #registerControllerAlwaysOnListener(Executor, ControllerAlwaysOnListener)}
-     * must be used.
-     *
-     * <p>Listeners are automatically unregistered when application process goes away
-     *
-     * @param listener user implementation of the {@link ControllerAlwaysOnListener}
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public void unregisterControllerAlwaysOnListener(
-            @NonNull ControllerAlwaysOnListener listener) {
-        mControllerAlwaysOnListener.unregister(listener);
-    }
-
-
-    /**
-     * Sets whether we dispatch NFC Tag intents to the package.
-     *
-     * <p>{@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
-     * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
-     * disallowed.
-     * <p>An app is added to the preference list with the allowed flag set to {@code true}
-     * when a Tag intent is dispatched to the package for the first time. This API is called
-     * by settings to note that the user wants to change this default preference.
-     *
-     * @param userId the user to whom this package name will belong to
-     * @param pkg the full name (i.e. com.google.android.tag) of the package that will be added to
-     * the preference list
-     * @param allow {@code true} to allow dispatching Tag intents to the package's activity,
-     * {@code false} otherwise
-     * @return the {@link #TagIntentAppPreferenceResult} value
-     * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
-     * {@code false}
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @TagIntentAppPreferenceResult
-    public int setTagIntentAppPreferenceForUser(@UserIdInt int userId,
-                @NonNull String pkg, boolean allow) {
-        Objects.requireNonNull(pkg, "pkg cannot be null");
-        if (!isTagIntentAppPreferenceSupported()) {
-            Log.e(TAG, "TagIntentAppPreference is not supported");
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->
-                sService.setTagIntentAppPreferenceForUser(userId, pkg, allow),
-                        TAG_INTENT_APP_PREF_RESULT_UNAVAILABLE);
-    }
-
-
-    /**
-     * Get the Tag dispatch preference list of the UserId.
-     *
-     * <p>This returns a mapping of package names for this user id to whether we dispatch Tag
-     * intents to the package. {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
-     * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if its package is
-     * mapped to {@code false}.
-     * <p>There are three different possible cases:
-     * <p>A package not being in the preference list.
-     * It does not contain any Tag intent filters or the user never triggers a Tag detection that
-     * matches the intent filter of the package.
-     * <p>A package being mapped to {@code true}.
-     * When a package has been launched by a tag detection for the first time, the package name is
-     * put to the map and by default mapped to {@code true}. The package will receive Tag intents as
-     * usual.
-     * <p>A package being mapped to {@code false}.
-     * The user chooses to disable this package and it will not receive any Tag intents anymore.
-     *
-     * @param userId the user to whom this preference list will belong to
-     * @return a map of the UserId which indicates the mapping from package name to
-     * boolean(allow status), otherwise return an empty map
-     * @throws UnsupportedOperationException if {@link isTagIntentAppPreferenceSupported} returns
-     * {@code false}
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @NonNull
-    public Map<String, Boolean> getTagIntentAppPreferenceForUser(@UserIdInt int userId) {
-        if (!isTagIntentAppPreferenceSupported()) {
-            Log.e(TAG, "TagIntentAppPreference is not supported");
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn( () ->
-            sService.getTagIntentAppPreferenceForUser(userId), Collections.emptyMap());
-    }
-
-    /**
-     * Checks if the device supports Tag Intent App Preference functionality.
-     *
-     * When supported, {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or
-     * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if
-     * {@link isTagIntentAllowed} returns {@code false}.
-     *
-     * @return {@code true} if the device supports Tag application preference, {@code false}
-     * otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable
-     */
-    @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
-    public boolean isTagIntentAppPreferenceSupported() {
-        if (!sHasNfcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isTagIntentAppPreferenceSupported(), false);
-    }
-
-   /**
-     * Notifies the system of a new polling loop.
-     *
-     * @param frame is the new frame.
-     *
-     * @hide
-     */
-    @TestApi
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public void notifyPollingLoop(@NonNull PollingFrame pollingFrame) {
-        callService(() ->  sService.notifyPollingLoop(pollingFrame));
-    }
-
-
-   /**
-     * Notifies the system of new HCE data for tests.
-     *
-     * @hide
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public void notifyTestHceData(int technology, byte[] data) {
-        callService(() ->  sService.notifyTestHceData(technology, data));
-    }
-
-    /** @hide */
-    interface ServiceCall {
-        void call() throws RemoteException;
-    }
-    /** @hide */
-    static void callService(ServiceCall call) {
-        try {
-            if (sService == null) {
-                attemptDeadServiceRecovery(new RemoteException("NFC Service is null"));
-            }
-            call.call();
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            try {
-                call.call();
-            } catch (RemoteException ee) {
-                ee.rethrowAsRuntimeException();
-            }
-        }
-    }
-    /** @hide */
-    interface ServiceCallReturn<T> {
-        T call() throws RemoteException;
-    }
-    /** @hide */
-    static <T> T callServiceReturn(ServiceCallReturn<T> call, T defaultReturn) {
-        try {
-            if (sService == null) {
-                attemptDeadServiceRecovery(new RemoteException("NFC Service is null"));
-            }
-            return call.call();
-        } catch (RemoteException e) {
-            attemptDeadServiceRecovery(e);
-            // Try one more time
-            try {
-                return call.call();
-            } catch (RemoteException ee) {
-                ee.rethrowAsRuntimeException();
-            }
-        }
-        return defaultReturn;
-    }
-
-   /**
-     * Notifies the system of a an HCE session being deactivated.
-     *     *
-     * @hide
-     */
-    @TestApi
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public void notifyHceDeactivated() {
-        callService(() ->  sService.notifyHceDeactivated());
-    }
-
-    /**
-     * Sets NFC charging feature.
-     * <p>This API is for the Settings application.
-     * @return True if successful
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean setWlcEnabled(boolean enable) {
-        if (!sHasNfcWlcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.setWlcEnabled(enable), false);
-    }
-
-    /**
-     * Checks NFC charging feature is enabled.
-     *
-     * @return True if NFC charging is enabled, false otherwise
-     * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
-     * is unavailable
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    public boolean isWlcEnabled() {
-        if (!sHasNfcWlcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.isWlcEnabled(), false);
-
-    }
-
-    /**
-     * A listener to be invoked when NFC controller always on state changes.
-     * <p>Register your {@code ControllerAlwaysOnListener} implementation with {@link
-     * NfcAdapter#registerWlcStateListener} and disable it with {@link
-     * NfcAdapter#unregisterWlcStateListenerListener}.
-     * @see #registerWlcStateListener
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    public interface WlcStateListener {
-        /**
-         * Called on NFC WLC state changes
-         */
-        void onWlcStateChanged(@NonNull WlcListenerDeviceInfo wlcListenerDeviceInfo);
-    }
-
-    /**
-     * Register a {@link WlcStateListener} to listen for NFC WLC state changes
-     * <p>The provided listener will be invoked by the given {@link Executor}.
-     *
-     * @param executor an {@link Executor} to execute given listener
-     * @param listener user implementation of the {@link WlcStateListener}
-     * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
-     * is unavailable
-     *
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    public void registerWlcStateListener(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull WlcStateListener listener) {
-        if (!sHasNfcWlcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        mNfcWlcStateListener.register(executor, listener);
-    }
-
-    /**
-     * Unregister the specified {@link WlcStateListener}
-     * <p>The same {@link WlcStateListener} object used when calling
-     * {@link #registerWlcStateListener(Executor, WlcStateListener)}
-     * must be used.
-     *
-     * <p>Listeners are automatically unregistered when application process goes away
-     *
-     * @param listener user implementation of the {@link WlcStateListener}a
-     * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
-     * is unavailable
-     *
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    public void unregisterWlcStateListener(
-            @NonNull WlcStateListener listener) {
-        if (!sHasNfcWlcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        mNfcWlcStateListener.unregister(listener);
-    }
-
-    /**
-     * Returns information on the NFC charging listener device
-     *
-     * @return Information on the NFC charging listener device
-     * @throws UnsupportedOperationException if FEATURE_NFC_CHARGING
-     * is unavailable
-     */
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-    @Nullable
-    public WlcListenerDeviceInfo getWlcListenerDeviceInfo() {
-        if (!sHasNfcWlcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        return callServiceReturn(() ->  sService.getWlcListenerDeviceInfo(), null);
-
-    }
-
-    /**
-     * Vendor NCI command success.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public static final int SEND_VENDOR_NCI_STATUS_SUCCESS = 0;
-    /**
-     * Vendor NCI command rejected.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public static final int SEND_VENDOR_NCI_STATUS_REJECTED = 1;
-    /**
-     * Vendor NCI command corrupted.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public static final int SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED  = 2;
-    /**
-     * Vendor NCI command failed with unknown reason.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public static final int SEND_VENDOR_NCI_STATUS_FAILED = 3;
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            SEND_VENDOR_NCI_STATUS_SUCCESS,
-            SEND_VENDOR_NCI_STATUS_REJECTED,
-            SEND_VENDOR_NCI_STATUS_MESSAGE_CORRUPTED,
-            SEND_VENDOR_NCI_STATUS_FAILED,
-    })
-    @interface SendVendorNciStatus {}
-
-    /**
-     * Message Type for NCI Command.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public static final int MESSAGE_TYPE_COMMAND = 1;
-
-    /**
-     * @hide
-     */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {
-            MESSAGE_TYPE_COMMAND,
-    })
-    @interface MessageType {}
-
-    /**
-     * Send Vendor specific Nci Messages with custom message type.
-     *
-     * The format of the NCI messages are defined in the NCI specification. The platform is
-     * responsible for fragmenting the payload if necessary.
-     *
-     * Note that mt (message type) is added at the beginning of method parameters as it is more
-     * distinctive than other parameters and was requested from vendor.
-     *
-     * @param mt message Type of the command
-     * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
-     *            the NCI specification
-     * @param oid opcode ID of the command. This is left to the OEM / vendor to decide
-     * @param payload containing vendor Nci message payload
-     * @return message send status
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public @SendVendorNciStatus int sendVendorNciMessage(@MessageType int mt,
-            @IntRange(from = 0, to = 15) int gid, @IntRange(from = 0) int oid,
-            @NonNull byte[] payload) {
-        Objects.requireNonNull(payload, "Payload must not be null");
-        return callServiceReturn(() ->  sService.sendVendorNciMessage(mt, gid, oid, payload),
-                SEND_VENDOR_NCI_STATUS_FAILED);
-    }
-
-    /**
-     * Register an {@link NfcVendorNciCallback} to listen for Nfc vendor responses and notifications
-     * <p>The provided callback will be invoked by the given {@link Executor}.
-     *
-     * <p>When first registering a callback, the callbacks's
-     * {@link NfcVendorNciCallback#onVendorNciCallBack(byte[])} is immediately invoked to
-     * notify the vendor notification.
-     *
-     * @param executor an {@link Executor} to execute given callback
-     * @param callback user implementation of the {@link NfcVendorNciCallback}
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void registerNfcVendorNciCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull NfcVendorNciCallback callback) {
-        mNfcVendorNciCallbackListener.register(executor, callback);
-    }
-
-    /**
-     * Unregister the specified {@link NfcVendorNciCallback}
-     *
-     * <p>The same {@link NfcVendorNciCallback} object used when calling
-     * {@link #registerNfcVendorNciCallback(Executor, NfcVendorNciCallback)} must be used.
-     *
-     * <p>Callbacks are automatically unregistered when application process goes away
-     *
-     * @param callback user implementation of the {@link NfcVendorNciCallback}
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void unregisterNfcVendorNciCallback(@NonNull NfcVendorNciCallback callback) {
-        mNfcVendorNciCallbackListener.unregister(callback);
-    }
-
-    /**
-     * Interface for receiving vendor NCI responses and notifications.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-    public interface NfcVendorNciCallback {
-        /**
-         * Invoked when a vendor specific NCI response is received.
-         *
-         * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
-         *            the NCI specification.
-         * @param oid opcode ID of the command. This is left to the OEM / vendor to decide.
-         * @param payload containing vendor Nci message payload.
-         */
-        @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-        void onVendorNciResponse(
-                @IntRange(from = 0, to = 15) int gid, int oid, @NonNull byte[] payload);
-
-        /**
-         * Invoked when a vendor specific NCI notification is received.
-         *
-         * @param gid group ID of the command. This needs to be one of the vendor reserved GIDs from
-         *            the NCI specification.
-         * @param oid opcode ID of the command. This is left to the OEM / vendor to decide.
-         * @param payload containing vendor Nci message payload.
-         */
-        @FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD)
-        void onVendorNciNotification(
-                @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload);
-    }
-
-    /**
-     * Used by data migration to indicate data migration is in progrerss or not.
-     *
-     * Note: This is @hide intentionally since the client is inside the NFC apex.
-     * @param inProgress true if migration is in progress, false once done.
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void indicateDataMigration(boolean inProgress) {
-        callService(() -> sService.indicateDataMigration(inProgress, mContext.getPackageName()));
-    }
-
-    /**
-     * Returns an instance of {@link NfcOemExtension} associated with {@link NfcAdapter} instance.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @NonNull public NfcOemExtension getNfcOemExtension() {
-        synchronized (sLock) {
-            if (!sHasNfcFeature) {
-                throw new UnsupportedOperationException();
-            }
-        }
-        return mNfcOemExtension;
-    }
-
-    /**
-     * Activity action: Bring up the settings page that allows the user to enable or disable tag
-     * intent reception for apps.
-     *
-     * <p>This will direct user to the settings page shows a list that asks users whether
-     * they want to allow or disallow the package to start an activity when a tag is discovered.
-     *
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
-    public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE =
-            "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE";
-
-    /**
-     * Checks whether the user has disabled the calling app from receiving NFC tag intents.
-     *
-     * <p>This method checks whether the caller package name is either not present in the user
-     * disabled list or is explicitly allowed by the user.
-     *
-     * @return {@code true} if an app is either not present in the list or is added to the list
-     * with the flag set to {@code true}. Otherwise, it returns {@code false}.
-     * It also returns {@code true} if {@link isTagIntentAppPreferenceSupported} returns
-     * {@code false}.
-     *
-     * @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
-    public boolean isTagIntentAllowed() {
-        if (!sHasNfcFeature) {
-            throw new UnsupportedOperationException();
-        }
-        if (!isTagIntentAppPreferenceSupported()) {
-            return true;
-        }
-        return callServiceReturn(() ->  sService.isTagIntentAllowed(mContext.getPackageName(),
-                UserHandle.myUserId()), false);
-    }
-}
diff --git a/nfc/java/android/nfc/NfcAntennaInfo.aidl b/nfc/java/android/nfc/NfcAntennaInfo.aidl
deleted file mode 100644
index d5e79fc..0000000
--- a/nfc/java/android/nfc/NfcAntennaInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable NfcAntennaInfo;
diff --git a/nfc/java/android/nfc/NfcAntennaInfo.java b/nfc/java/android/nfc/NfcAntennaInfo.java
deleted file mode 100644
index c57b2e0..0000000
--- a/nfc/java/android/nfc/NfcAntennaInfo.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Contains information on all available Nfc
- * antennas on an Android device as well as information
- * on the device itself in relation positioning of the
- * antennas.
- */
-public final class NfcAntennaInfo implements Parcelable {
-    // Width of the device in millimeters.
-    private final int mDeviceWidth;
-    // Height of the device in millimeters.
-    private final int mDeviceHeight;
-    // Whether the device is foldable.
-    private final boolean mDeviceFoldable;
-    // All available Nfc Antennas on the device.
-    private final List<AvailableNfcAntenna> mAvailableNfcAntennas;
-
-    public NfcAntennaInfo(int deviceWidth, int deviceHeight, boolean deviceFoldable,
-            @NonNull List<AvailableNfcAntenna> availableNfcAntennas) {
-        this.mDeviceWidth = deviceWidth;
-        this.mDeviceHeight = deviceHeight;
-        this.mDeviceFoldable = deviceFoldable;
-        this.mAvailableNfcAntennas = availableNfcAntennas;
-    }
-
-    /**
-     * Width of the device in millimeters.
-     */
-    public int getDeviceWidth() {
-        return mDeviceWidth;
-    }
-
-    /**
-     * Height of the device in millimeters.
-     */
-    public int getDeviceHeight() {
-        return mDeviceHeight;
-    }
-
-    /**
-     * Whether the device is foldable. When the device is foldable,
-     * the 0, 0 is considered to be top-left when the device is unfolded and
-     * the screens are facing the user. For non-foldable devices 0, 0
-     * is top-left when the user is facing the screen.
-     */
-    public boolean isDeviceFoldable() {
-        return mDeviceFoldable;
-    }
-
-    /**
-     * Get all NFC antennas that exist on the device.
-     */
-    @NonNull
-    public List<AvailableNfcAntenna> getAvailableNfcAntennas() {
-        return mAvailableNfcAntennas;
-    }
-
-    private NfcAntennaInfo(Parcel in) {
-        this.mDeviceWidth = in.readInt();
-        this.mDeviceHeight = in.readInt();
-        this.mDeviceFoldable = in.readByte() != 0;
-        this.mAvailableNfcAntennas = new ArrayList<>();
-        in.readTypedList(this.mAvailableNfcAntennas,
-                AvailableNfcAntenna.CREATOR);
-    }
-
-    public static final @NonNull Parcelable.Creator<NfcAntennaInfo> CREATOR =
-            new Parcelable.Creator<NfcAntennaInfo>() {
-        @Override
-        public NfcAntennaInfo createFromParcel(Parcel in) {
-            return new NfcAntennaInfo(in);
-        }
-
-        @Override
-        public NfcAntennaInfo[] newArray(int size) {
-            return new NfcAntennaInfo[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mDeviceWidth);
-        dest.writeInt(mDeviceHeight);
-        dest.writeByte((byte) (mDeviceFoldable ? 1 : 0));
-        dest.writeTypedList(mAvailableNfcAntennas, 0);
-    }
-}
diff --git a/nfc/java/android/nfc/NfcControllerAlwaysOnListener.java b/nfc/java/android/nfc/NfcControllerAlwaysOnListener.java
deleted file mode 100644
index 6ae58fd..0000000
--- a/nfc/java/android/nfc/NfcControllerAlwaysOnListener.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * @hide
- */
-public class NfcControllerAlwaysOnListener extends INfcControllerAlwaysOnListener.Stub {
-    private static final String TAG = NfcControllerAlwaysOnListener.class.getSimpleName();
-
-    private final INfcAdapter mAdapter;
-
-    private final Map<ControllerAlwaysOnListener, Executor> mListenerMap = new HashMap<>();
-
-    private boolean mCurrentState = false;
-    private boolean mIsRegistered = false;
-
-    public NfcControllerAlwaysOnListener(@NonNull INfcAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    /**
-     * Register a {@link ControllerAlwaysOnListener} with this
-     * {@link NfcControllerAlwaysOnListener}
-     *
-     * @param executor an {@link Executor} to execute given listener
-     * @param listener user implementation of the {@link ControllerAlwaysOnListener}
-     */
-    public void register(@NonNull Executor executor,
-            @NonNull ControllerAlwaysOnListener listener) {
-        try {
-            if (!mAdapter.isControllerAlwaysOnSupported()) {
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to register");
-            return;
-        }
-        synchronized (this) {
-            if (mListenerMap.containsKey(listener)) {
-                return;
-            }
-
-            mListenerMap.put(listener, executor);
-            if (!mIsRegistered) {
-                try {
-                    mAdapter.registerControllerAlwaysOnListener(this);
-                    mIsRegistered = true;
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to register");
-                }
-            }
-        }
-    }
-
-    /**
-     * Unregister the specified {@link ControllerAlwaysOnListener}
-     *
-     * @param listener user implementation of the {@link ControllerAlwaysOnListener}
-     */
-    public void unregister(@NonNull ControllerAlwaysOnListener listener) {
-        try {
-            if (!mAdapter.isControllerAlwaysOnSupported()) {
-                return;
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to unregister");
-            return;
-        }
-        synchronized (this) {
-            if (!mListenerMap.containsKey(listener)) {
-                return;
-            }
-
-            mListenerMap.remove(listener);
-
-            if (mListenerMap.isEmpty() && mIsRegistered) {
-                try {
-                    mAdapter.unregisterControllerAlwaysOnListener(this);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to unregister");
-                }
-                mIsRegistered = false;
-            }
-        }
-    }
-
-    private void sendCurrentState(@NonNull ControllerAlwaysOnListener listener) {
-        synchronized (this) {
-            Executor executor = mListenerMap.get(listener);
-
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                executor.execute(() -> listener.onControllerAlwaysOnChanged(
-                        mCurrentState));
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    @Override
-    public void onControllerAlwaysOnChanged(boolean isEnabled) {
-        synchronized (this) {
-            mCurrentState = isEnabled;
-            for (ControllerAlwaysOnListener cb : mListenerMap.keySet()) {
-                sendCurrentState(cb);
-            }
-        }
-    }
-}
-
diff --git a/nfc/java/android/nfc/NfcEvent.java b/nfc/java/android/nfc/NfcEvent.java
deleted file mode 100644
index aff4f52..0000000
--- a/nfc/java/android/nfc/NfcEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-/**
- * Wraps information associated with any NFC event.
- *
- * <p>Immutable object, with direct access to the (final) fields.
- *
- * <p>An {@link NfcEvent} object is usually included in callbacks from
- * {@link NfcAdapter}. Check the documentation of the callback to see
- * which fields may be set.
- *
- * <p>This wrapper object is used (instead of parameters
- * in the callback) because it allows new fields to be added without breaking
- * API compatibility.
- *
- * @see NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete
- * @see NfcAdapter.CreateNdefMessageCallback#createNdefMessage
- */
-public final class NfcEvent {
-    /**
-     * The {@link NfcAdapter} associated with the NFC event.
-     */
-    public final NfcAdapter nfcAdapter;
-
-    /**
-     * The major LLCP version number of the peer associated with the NFC event.
-     */
-    public final int peerLlcpMajorVersion;
-
-    /**
-     * The minor LLCP version number of the peer associated with the NFC event.
-     */
-    public final int peerLlcpMinorVersion;
-
-    NfcEvent(NfcAdapter nfcAdapter, byte peerLlcpVersion) {
-        this.nfcAdapter = nfcAdapter;
-        this.peerLlcpMajorVersion = (peerLlcpVersion & 0xF0) >> 4;
-        this.peerLlcpMinorVersion = peerLlcpVersion & 0x0F;
-    }
-}
diff --git a/nfc/java/android/nfc/NfcFrameworkInitializer.java b/nfc/java/android/nfc/NfcFrameworkInitializer.java
deleted file mode 100644
index 1ab8a1e..0000000
--- a/nfc/java/android/nfc/NfcFrameworkInitializer.java
+++ /dev/null
@@ -1,71 +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.nfc;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.app.SystemServiceRegistry;
-import android.content.Context;
-
-/**
- * Class for performing registration for Nfc service.
- *
- * @hide
- */
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public class NfcFrameworkInitializer {
-    private NfcFrameworkInitializer() {}
-
-    private static volatile NfcServiceManager sNfcServiceManager;
-
-    /**
-     * Sets an instance of {@link NfcServiceManager} that allows
-     * the nfc mainline module to register/obtain nfc binder services. This is called
-     * by the platform during the system initialization.
-     *
-     * @param nfcServiceManager instance of {@link NfcServiceManager} that allows
-     * the nfc mainline module to register/obtain nfcd binder services.
-     */
-    public static void setNfcServiceManager(
-            @NonNull NfcServiceManager nfcServiceManager) {
-        if (sNfcServiceManager != null) {
-            throw new IllegalStateException("setNfcServiceManager called twice!");
-        }
-
-        if (nfcServiceManager == null) {
-            throw new IllegalArgumentException("nfcServiceManager must not be null");
-        }
-
-        sNfcServiceManager = nfcServiceManager;
-    }
-
-    /** @hide */
-    public static NfcServiceManager getNfcServiceManager() {
-        return sNfcServiceManager;
-    }
-
-    /**
-     * Called by {@link SystemServiceRegistry}'s static initializer and registers NFC service
-     * to {@link Context}, so that {@link Context#getSystemService} can return them.
-     *
-     * @throws IllegalStateException if this is called from anywhere besides
-     * {@link SystemServiceRegistry}
-     */
-    public static void registerServiceWrappers() {
-        SystemServiceRegistry.registerContextAwareService(Context.NFC_SERVICE,
-                NfcManager.class, context -> new NfcManager(context));
-    }
-}
diff --git a/nfc/java/android/nfc/NfcManager.java b/nfc/java/android/nfc/NfcManager.java
deleted file mode 100644
index 644e312..0000000
--- a/nfc/java/android/nfc/NfcManager.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.SystemService;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.os.Build;
-
-/**
- * High level manager used to obtain an instance of an {@link NfcAdapter}.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with {@link Context#NFC_SERVICE} to create an {@link NfcManager},
- * then call {@link #getDefaultAdapter} to obtain the {@link NfcAdapter}.
- * <p>
- * Alternately, you can just call the static helper
- * {@link NfcAdapter#getDefaultAdapter(android.content.Context)}.
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about using NFC, read the
- * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
- * </div>
- *
- * @see NfcAdapter#getDefaultAdapter(android.content.Context)
- */
-@SystemService(Context.NFC_SERVICE)
-public final class NfcManager {
-    private final NfcAdapter mAdapter;
-
-    /**
-     * @hide
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public NfcManager(Context context) {
-        NfcAdapter adapter;
-        context = context.getApplicationContext();
-        if (context == null) {
-            throw new IllegalArgumentException(
-                    "context not associated with any application (using a mock context?)");
-        }
-        try {
-            adapter = NfcAdapter.getNfcAdapter(context);
-        } catch (UnsupportedOperationException e) {
-            adapter = null;
-        }
-        mAdapter = adapter;
-    }
-
-    /**
-     * Get the default NFC Adapter for this device.
-     *
-     * @return the default NFC Adapter
-     */
-    public NfcAdapter getDefaultAdapter() {
-        return mAdapter;
-    }
-}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
deleted file mode 100644
index b46e343..0000000
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
-import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
-import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
-import static android.nfc.cardemulation.CardEmulation.routeIntToString;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.DurationMillisLong;
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.nfc.cardemulation.ApduServiceInfo;
-import android.nfc.cardemulation.CardEmulation;
-import android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.se.omapi.Reader;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * Used for OEM extension APIs.
- * This class holds all the APIs and callbacks defined for OEMs/vendors to extend the NFC stack
- * for their proprietary features.
- *
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public final class NfcOemExtension {
-    private static final String TAG = "NfcOemExtension";
-    private static final int OEM_EXTENSION_RESPONSE_THRESHOLD_MS = 2000;
-    private static final int TYPE_TECHNOLOGY = 0;
-    private static final int TYPE_PROTOCOL = 1;
-    private static final int TYPE_AID = 2;
-    private static final int TYPE_SYSTEMCODE = 3;
-
-    private final NfcAdapter mAdapter;
-    private final NfcOemExtensionCallback mOemNfcExtensionCallback;
-    private boolean mIsRegistered = false;
-    private final Map<Callback, Executor> mCallbackMap = new HashMap<>();
-    private final Context mContext;
-    private final Object mLock = new Object();
-    private boolean mCardEmulationActivated = false;
-    private boolean mRfFieldActivated = false;
-    private boolean mRfDiscoveryStarted = false;
-    private boolean mEeListenActivated = false;
-
-    /**
-     * Broadcast Action: Sent on NFC stack initialization when NFC OEM extensions are enabled.
-     * <p> OEM extension modules should use this intent to start their extension service </p>
-     * @hide
-     */
-    public static final String ACTION_OEM_EXTENSION_INIT = "android.nfc.action.OEM_EXTENSION_INIT";
-
-    /**
-     * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
-     * Enables the controller in default mode when NFC is disabled (existing API behavior).
-     * works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int ENABLE_DEFAULT = NfcAdapter.CONTROLLER_ALWAYS_ON_MODE_DEFAULT;
-
-    /**
-     * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
-     * Enables the controller in transparent mode when NFC is disabled.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int ENABLE_TRANSPARENT = 2;
-
-    /**
-     * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
-     * Enables the controller and initializes and enables the EE subsystem when NFC is disabled.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int ENABLE_EE = 3;
-
-    /**
-     * Mode Type for {@link #setControllerAlwaysOnMode(int)}.
-     * Disable the Controller Always On Mode.
-     * works same as {@link NfcAdapter#setControllerAlwaysOn(boolean)}.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int DISABLE = NfcAdapter.CONTROLLER_ALWAYS_ON_DISABLE;
-
-    /**
-     * Possible controller modes for {@link #setControllerAlwaysOnMode(int)}.
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "" }, value = {
-        ENABLE_DEFAULT,
-        ENABLE_TRANSPARENT,
-        ENABLE_EE,
-        DISABLE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ControllerMode{}
-
-    /**
-     * Technology Type for {@link #getActiveNfceeList()}.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int NFCEE_TECH_NONE = 0;
-
-    /**
-     * Technology Type for {@link #getActiveNfceeList()}.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int NFCEE_TECH_A = 1;
-
-    /**
-     * Technology Type for {@link #getActiveNfceeList()}.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int NFCEE_TECH_B = 1 << 1;
-
-    /**
-     * Technology Type for {@link #getActiveNfceeList()}.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int NFCEE_TECH_F = 1 << 2;
-
-    /**
-     * Nfc technology flags for {@link #getActiveNfceeList()}.
-     *
-     * @hide
-     */
-    @IntDef(flag = true, value = {
-        NFCEE_TECH_NONE,
-        NFCEE_TECH_A,
-        NFCEE_TECH_B,
-        NFCEE_TECH_F,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface NfceeTechnology {}
-
-    /**
-     * Event that Host Card Emulation is activated.
-     */
-    public static final int HCE_ACTIVATE = 1;
-    /**
-     * Event that some data is transferred in Host Card Emulation.
-     */
-    public static final int HCE_DATA_TRANSFERRED = 2;
-    /**
-     * Event that Host Card Emulation is deactivated.
-     */
-    public static final int HCE_DEACTIVATE = 3;
-    /**
-     * Possible events from {@link Callback#onHceEventReceived}.
-     *
-     * @hide
-     */
-    @IntDef(value = {
-            HCE_ACTIVATE,
-            HCE_DATA_TRANSFERRED,
-            HCE_DEACTIVATE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface HostCardEmulationAction {}
-
-    /**
-     * Status code returned when the polling state change request succeeded.
-     * @see #pausePolling()
-     * @see #resumePolling()
-     */
-    public static final int POLLING_STATE_CHANGE_SUCCEEDED = 1;
-    /**
-     * Status code returned when the polling state change request is already in
-     * required state.
-     * @see #pausePolling()
-     * @see #resumePolling()
-     */
-    public static final int POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE = 2;
-    /**
-     * Possible status codes for {@link #pausePolling()} and
-     * {@link #resumePolling()}.
-     * @hide
-     */
-    @IntDef(value = {
-            POLLING_STATE_CHANGE_SUCCEEDED,
-            POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface PollingStateChangeStatusCode {}
-
-    /**
-     * Status OK
-     */
-    public static final int STATUS_OK = 0;
-    /**
-     * Status unknown error
-     */
-    public static final int STATUS_UNKNOWN_ERROR = 1;
-
-    /**
-     * Status codes passed to OEM extension callbacks.
-     *
-     * @hide
-     */
-    @IntDef(value = {
-            STATUS_OK,
-            STATUS_UNKNOWN_ERROR
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface StatusCode {}
-
-    /**
-     * Routing commit succeeded.
-     */
-    public static final int COMMIT_ROUTING_STATUS_OK = 0;
-    /**
-     * Routing commit failed.
-     */
-    public static final int COMMIT_ROUTING_STATUS_FAILED = 3;
-    /**
-     * Routing commit failed due to the update is in progress.
-     */
-    public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6;
-
-    /**
-     * Status codes returned when calling {@link #forceRoutingTableCommit()}
-     * @hide
-     */
-    @IntDef(prefix = "COMMIT_ROUTING_STATUS_", value = {
-            COMMIT_ROUTING_STATUS_OK,
-            COMMIT_ROUTING_STATUS_FAILED,
-            COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface CommitRoutingStatusCode {}
-    /**
-     * Interface for Oem extensions for NFC.
-     */
-    public interface Callback {
-        /**
-         * Notify Oem to tag is connected or not
-         * ex - if tag is connected  notify cover and Nfctest app if app is in testing mode
-         *
-         * @param connected status of the tag true if tag is connected otherwise false
-         */
-        void onTagConnected(boolean connected);
-
-        /**
-         * Update the Nfc Adapter State
-         * @param state new state that need to be updated
-         */
-        void onStateUpdated(@NfcAdapter.AdapterState int state);
-        /**
-         * Check if NfcService apply routing method need to be skipped for
-         * some feature.
-         * @param isSkipped The {@link Consumer} to be completed. If apply routing can be skipped,
-         *                  the {@link Consumer#accept(Object)} should be called with
-         *                  {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         */
-        void onApplyRouting(@NonNull Consumer<Boolean> isSkipped);
-        /**
-         * Check if NfcService ndefRead method need to be skipped To skip
-         * and start checking for presence of tag
-         * @param isSkipped The {@link Consumer} to be completed. If Ndef read can be skipped,
-         *                  the {@link Consumer#accept(Object)} should be called with
-         *                  {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         */
-        void onNdefRead(@NonNull Consumer<Boolean> isSkipped);
-        /**
-         * Method to check if Nfc is allowed to be enabled by OEMs.
-         * @param isAllowed The {@link Consumer} to be completed. If enabling NFC is allowed,
-         *                  the {@link Consumer#accept(Object)} should be called with
-         *                  {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         * false if NFC cannot be enabled at this time.
-         */
-        void onEnableRequested(@NonNull Consumer<Boolean> isAllowed);
-        /**
-         * Method to check if Nfc is allowed to be disabled by OEMs.
-         * @param isAllowed The {@link Consumer} to be completed. If disabling NFC is allowed,
-         *                  the {@link Consumer#accept(Object)} should be called with
-         *                  {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         * false if NFC cannot be disabled at this time.
-         */
-        void onDisableRequested(@NonNull Consumer<Boolean> isAllowed);
-
-        /**
-         * Callback to indicate that Nfc starts to boot.
-         */
-        void onBootStarted();
-
-        /**
-         * Callback to indicate that Nfc starts to enable.
-         */
-        void onEnableStarted();
-
-        /**
-         * Callback to indicate that Nfc starts to disable.
-         */
-        void onDisableStarted();
-
-        /**
-         * Callback to indicate if NFC boots successfully or not.
-         * @param status the status code indicating if boot finished successfully
-         */
-        void onBootFinished(@StatusCode int status);
-
-        /**
-         * Callback to indicate if NFC is successfully enabled.
-         * @param status the status code indicating if enable finished successfully
-         */
-        void onEnableFinished(@StatusCode int status);
-
-        /**
-         * Callback to indicate if NFC is successfully disabled.
-         * @param status the status code indicating if disable finished successfully
-         */
-        void onDisableFinished(@StatusCode int status);
-
-        /**
-         * Check if NfcService tag dispatch need to be skipped.
-         * @param isSkipped The {@link Consumer} to be completed. If tag dispatch can be skipped,
-         *                  the {@link Consumer#accept(Object)} should be called with
-         *                  {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         */
-        void onTagDispatch(@NonNull Consumer<Boolean> isSkipped);
-
-        /**
-         * Notifies routing configuration is changed.
-         * @param isCommitRoutingSkipped The {@link Consumer} to be
-         * completed. If routing commit should be skipped,
-         * the {@link Consumer#accept(Object)} should be called with
-         * {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}.
-         */
-        void onRoutingChanged(@NonNull Consumer<Boolean> isCommitRoutingSkipped);
-
-        /**
-         * API to activate start stop cpu boost on hce event.
-         *
-         * <p>When HCE is activated, transferring data, and deactivated,
-         * must call this method to activate, start and stop cpu boost respectively.
-         * @param action Flag indicating actions to activate, start and stop cpu boost.
-         */
-        void onHceEventReceived(@HostCardEmulationAction int action);
-
-        /**
-         * API to notify when reader option has been changed using
-         * {@link NfcAdapter#enableReaderOption(boolean)} by some app.
-         * @param enabled Flag indicating ReaderMode enabled/disabled
-         */
-        void onReaderOptionChanged(boolean enabled);
-
-        /**
-        * Notifies NFC is activated in listen mode.
-        * NFC Forum NCI-2.3 ch.5.2.6 specification
-        *
-        * <p>NFCC is ready to communicate with a Card reader
-        *
-        * @param isActivated true, if card emulation activated, else de-activated.
-        */
-        void onCardEmulationActivated(boolean isActivated);
-
-        /**
-        * Notifies the Remote NFC Endpoint RF Field is activated.
-        * NFC Forum NCI-2.3 ch.5.3 specification
-        *
-        * @param isActivated true, if RF Field is ON, else RF Field is OFF.
-        */
-        void onRfFieldActivated(boolean isActivated);
-
-        /**
-        * Notifies the NFC RF discovery is started or in the IDLE state.
-        * NFC Forum NCI-2.3 ch.5.2 specification
-        *
-        * @param isDiscoveryStarted true, if RF discovery started, else RF state is Idle.
-        */
-        void onRfDiscoveryStarted(boolean isDiscoveryStarted);
-
-        /**
-        * Notifies the NFCEE (NFC Execution Environment) Listen has been activated.
-        *
-        * @param isActivated true, if EE Listen is ON, else EE Listen is OFF.
-        */
-        void onEeListenActivated(boolean isActivated);
-
-        /**
-        * Notifies that some NFCEE (NFC Execution Environment) has been updated.
-        *
-        * <p> This indicates that some applet has been installed/updated/removed in
-        * one of the NFCEE's.
-        * </p>
-        */
-        void onEeUpdated();
-
-        /**
-         * Gets the intent to find the OEM package in the OEM App market. If the consumer returns
-         * {@code null} or a timeout occurs, the intent from the first available package will be
-         * used instead.
-         *
-         * @param packages the OEM packages name stored in the tag
-         * @param intentConsumer The {@link Consumer} to be completed.
-         *                       The {@link Consumer#accept(Object)} should be called with
-         *                       the Intent required.
-         *
-         */
-        void onGetOemAppSearchIntent(@NonNull List<String> packages,
-                                     @NonNull Consumer<Intent> intentConsumer);
-
-        /**
-         * Checks if the NDEF message contains any specific OEM package executable content
-         *
-         * @param tag        the {@link android.nfc.Tag Tag}
-         * @param message NDEF Message to read from tag
-         * @param hasOemExecutableContent The {@link Consumer} to be completed. If there is
-         *                                OEM package executable content, the
-         *                                {@link Consumer#accept(Object)} should be called with
-         *                                {@link Boolean#TRUE}, otherwise call with
-         *                                {@link Boolean#FALSE}.
-         */
-        void onNdefMessage(@NonNull Tag tag, @NonNull NdefMessage message,
-                           @NonNull Consumer<Boolean> hasOemExecutableContent);
-
-        /**
-         * Callback to indicate the app chooser activity should be launched for handling CE
-         * transaction. This is invoked for example when there are more than 1 app installed that
-         * can handle the HCE transaction. OEMs can launch the Activity based
-         * on their requirement.
-         *
-         * @param selectedAid the selected AID from APDU
-         * @param services {@link ApduServiceInfo} of the service triggering the activity
-         * @param failedComponent the component failed to be resolved
-         * @param category the category of the service
-         */
-        void onLaunchHceAppChooserActivity(@NonNull String selectedAid,
-                                           @NonNull List<ApduServiceInfo> services,
-                                           @NonNull ComponentName failedComponent,
-                                           @NonNull String category);
-
-        /**
-         * Callback to indicate tap again dialog should be launched for handling HCE transaction.
-         * This is invoked for example when a CE service needs the device to unlocked before
-         * handling the transaction. OEMs can launch the Activity based on their requirement.
-         *
-         * @param service {@link ApduServiceInfo} of the service triggering the dialog
-         * @param category the category of the service
-         */
-        void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category);
-
-        /**
-         * Callback to indicate that routing table is full and the OEM can optionally launch a
-         * dialog to request the user to remove some Card Emulation apps from the device to free
-         * routing table space.
-         */
-        void onRoutingTableFull();
-
-        /**
-         * Callback when OEM specified log event are notified.
-         * @param item the log items that contains log information of NFC event.
-         */
-        void onLogEventNotified(@NonNull OemLogItems item);
-
-        /**
-         * Callback to to extract OEM defined packages from given NDEF message when
-         * a NFC tag is detected. These are used to handle NFC tags encoded with a
-         * proprietary format for storing app name (Android native app format).
-         *
-         * @param message NDEF message containing OEM package names
-         * @param packageConsumer The {@link Consumer} to be completed.
-         *                        The {@link Consumer#accept(Object)} should be called with
-         *                        the list of package names.
-         */
-        void onExtractOemPackages(@NonNull NdefMessage message,
-                @NonNull Consumer<List<String>> packageConsumer);
-    }
-
-
-    /**
-     * Constructor to be used only by {@link NfcAdapter}.
-     */
-    NfcOemExtension(@NonNull Context context, @NonNull NfcAdapter adapter) {
-        mContext = context;
-        mAdapter = adapter;
-        mOemNfcExtensionCallback = new NfcOemExtensionCallback();
-    }
-
-    /**
-     * Get an instance of {@link T4tNdefNfcee} object for performing T4T (Type-4 Tag)
-     * NDEF (NFC Data Exchange Format) NFCEE (NFC Execution Environment) operations.
-     * This can be used to write NDEF data to emulate a T4T tag in an NFCEE
-     * (NFC Execution Environment - eSE, SIM, etc). Refer to the NFC forum specification
-     * "NFCForum-TS-NCI-2.3 section 10.4" and "NFCForum-TS-T4T-1.1 section 4.2" for more details.
-     *
-     * This is a singleton object which shall be used by OEM extension module to do NDEF-NFCEE
-     * read/write operations.
-     *
-     * <p>Returns {@link T4tNdefNfcee}
-     * <p>Does not cause any RF activity and does not block.
-     * @return NFC Data Exchange Format (NDEF) NFC Execution Environment (NFCEE) object
-     * @hide
-     */
-    @SystemApi
-    @NonNull
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public T4tNdefNfcee getT4tNdefNfcee() {
-        return T4tNdefNfcee.getInstance();
-    }
-
-    /**
-     * Register an {@link Callback} to listen for NFC oem extension callbacks
-     * Multiple clients can register and callbacks will be invoked asynchronously.
-     *
-     * <p>The provided callback will be invoked by the given {@link Executor}.
-     * As part of {@link #registerCallback(Executor, Callback)} the
-     * {@link Callback} will be invoked with current NFC state
-     * before the {@link #registerCallback(Executor, Callback)} function completes.
-     *
-     * @param executor an {@link Executor} to execute given callback
-     * @param callback oem implementation of {@link Callback}
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void registerCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull Callback callback) {
-        synchronized (mLock) {
-            if (executor == null || callback == null) {
-                Log.e(TAG, "Executor and Callback must not be null!");
-                throw new IllegalArgumentException();
-            }
-
-            if (mCallbackMap.containsKey(callback)) {
-                Log.e(TAG, "Callback already registered. Unregister existing callback before"
-                        + "registering");
-                throw new IllegalArgumentException();
-            }
-            mCallbackMap.put(callback, executor);
-            if (!mIsRegistered) {
-                NfcAdapter.callService(() -> {
-                    NfcAdapter.sService.registerOemExtensionCallback(mOemNfcExtensionCallback);
-                    mIsRegistered = true;
-                });
-            } else {
-                updateNfCState(callback, executor);
-            }
-        }
-    }
-
-    private void updateNfCState(Callback callback, Executor executor) {
-        if (callback != null) {
-            Log.i(TAG, "updateNfCState");
-            executor.execute(() -> {
-                callback.onCardEmulationActivated(mCardEmulationActivated);
-                callback.onRfFieldActivated(mRfFieldActivated);
-                callback.onRfDiscoveryStarted(mRfDiscoveryStarted);
-                callback.onEeListenActivated(mEeListenActivated);
-            });
-        }
-    }
-
-    /**
-     * Unregister the specified {@link Callback}
-     *
-     * <p>The same {@link Callback} object used when calling
-     * {@link #registerCallback(Executor, Callback)} must be used.
-     *
-     * <p>Callbacks are automatically unregistered when an application process goes away
-     *
-     * @param callback oem implementation of {@link Callback}
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void unregisterCallback(@NonNull Callback callback) {
-        synchronized (mLock) {
-            if (!mCallbackMap.containsKey(callback) || !mIsRegistered) {
-                Log.e(TAG, "Callback not registered");
-                throw new IllegalArgumentException();
-            }
-            if (mCallbackMap.size() == 1) {
-                NfcAdapter.callService(() -> {
-                    NfcAdapter.sService.unregisterOemExtensionCallback(mOemNfcExtensionCallback);
-                    mIsRegistered = false;
-                    mCallbackMap.remove(callback);
-                });
-            } else {
-                mCallbackMap.remove(callback);
-            }
-        }
-    }
-
-    /**
-     * Clear NfcService preference, interface method to clear NFC preference values on OEM specific
-     * events. For ex: on soft reset, Nfc default values needs to be overridden by OEM defaults.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void clearPreference() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.clearPreference());
-    }
-
-    /**
-     * Get the screen state from system and set it to current screen state.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void synchronizeScreenState() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.setScreenState());
-    }
-
-    /**
-     * Check if the firmware needs updating.
-     *
-     * <p>If an update is needed, a firmware will be triggered when NFC is disabled.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void maybeTriggerFirmwareUpdate() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.checkFirmware());
-    }
-
-    /**
-     * Get the Active NFCEE (NFC Execution Environment) List
-     *
-     * @return Map< String, @NfceeTechnology Integer >
-     *         A HashMap where keys are activated secure elements and
-     *         the values are bitmap of technologies supported by each secure element:
-     *          NFCEE_TECH_A == 0x1
-     *          NFCEE_TECH_B == 0x2
-     *          NFCEE_TECH_F == 0x4
-     *         and keys can contain "eSE" and "SIM" with a number,
-     *         in case of failure an empty map is returned.
-     *         @see Reader#getName() for the list of possible NFCEE names.
-     */
-    @NonNull
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public Map<String, Integer> getActiveNfceeList() {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sService.fetchActiveNfceeList(), new HashMap<String, Integer>());
-    }
-
-    /**
-     * Sets NFC controller always on feature.
-     * <p>This API is for the NFCC internal state management. It allows to discriminate
-     * the controller function from the NFC function by keeping the NFC controller on without
-     * any NFC RF enabled if necessary.
-     * <p>This call is asynchronous, register listener {@link NfcAdapter.ControllerAlwaysOnListener}
-     * by {@link NfcAdapter#registerControllerAlwaysOnListener} to find out when the operation is
-     * complete.
-     * <p> Note: This adds more always on modes on top of existing
-     * {@link NfcAdapter#setControllerAlwaysOn(boolean)} API which can be used to set the NFCC in
-     * only {@link #ENABLE_DEFAULT} and {@link #DISABLE} modes.
-     * @param mode one of {@link ControllerMode} modes
-     * @throws UnsupportedOperationException if
-     *   <li> if FEATURE_NFC, FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF,
-     *   FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC and FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE
-     *   are unavailable </li>
-     *   <li> if the feature is unavailable @see NfcAdapter#isNfcControllerAlwaysOnSupported() </li>
-     * @hide
-     * @see NfcAdapter#setControllerAlwaysOn(boolean)
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
-    public void setControllerAlwaysOnMode(@ControllerMode int mode) {
-        if (!NfcAdapter.sHasNfcFeature && !NfcAdapter.sHasCeFeature) {
-            throw new UnsupportedOperationException();
-        }
-        NfcAdapter.callService(() -> NfcAdapter.sService.setControllerAlwaysOn(mode));
-    }
-
-    /**
-     * Triggers NFC initialization. If OEM extension is registered
-     * (indicated via `enable_oem_extension` NFC overlay), the NFC stack initialization at bootup
-     * is delayed until the OEM extension app triggers the initialization via this call.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void triggerInitialization() {
-        NfcAdapter.callService(() -> NfcAdapter.sService.triggerInitialization());
-    }
-
-    /**
-     * Gets the last user toggle status.
-     * @return true if NFC is set to ON, false otherwise
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean hasUserEnabledNfc() {
-        return NfcAdapter.callServiceReturn(() -> NfcAdapter.sService.getSettingStatus(), false);
-    }
-
-    /**
-     * Checks if the tag is present or not.
-     * @return true if the tag is present, false otherwise
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isTagPresent() {
-        return NfcAdapter.callServiceReturn(() -> NfcAdapter.sService.isTagPresent(), false);
-    }
-
-    /**
-     * Pauses NFC tag reader mode polling for a {@code timeoutInMs} millisecond.
-     * In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely.
-     * Use {@link #resumePolling()} to resume the polling.
-     * Use {@link #getMaxPausePollingTimeoutMs()} to check the max timeout value.
-     * @param timeoutInMs the pause polling duration in millisecond.
-     * @return status of the operation
-     * @throws IllegalArgumentException if timeoutInMs value is invalid
-     *         (0 < timeoutInMs < max).
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public @PollingStateChangeStatusCode int pausePolling(@DurationMillisLong long timeoutInMs) {
-        return NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sService.pausePolling(timeoutInMs),
-                POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE);
-    }
-
-    /**
-     * Resumes default NFC tag reader mode polling for the current device state if polling is
-     * paused. Calling this while already in polling is a no-op.
-     * @return status of the operation
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public @PollingStateChangeStatusCode int resumePolling() {
-        return NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sService.resumePolling(),
-                POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE);
-    }
-
-    /**
-     * Gets the max pause polling timeout value in millisecond.
-     * @return long integer representing the max timeout
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @DurationMillisLong
-    public long getMaxPausePollingTimeoutMills() {
-        return NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sService.getMaxPausePollingTimeoutMs(), 0L);
-    }
-
-    /**
-     * Set whether to enable auto routing change or not (enabled by default).
-     * If disabled, routing targets are limited to a single off-host destination.
-     *
-     * @param state status of auto routing change, true if enable, otherwise false
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    public void setAutoChangeEnabled(boolean state) {
-        NfcAdapter.callService(() ->
-                NfcAdapter.sCardEmulationService.setAutoChangeStatus(state));
-    }
-
-    /**
-     * Check if auto routing change is enabled or not.
-     *
-     * @return true if enabled, otherwise false
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isAutoChangeEnabled() {
-        return NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sCardEmulationService.isAutoChangeEnabled(), false);
-    }
-
-    /**
-     * Get current routing status
-     *
-     * @return {@link RoutingStatus} indicating the default route, default ISO-DEP
-     * route and default off-host route.
-     */
-    @NonNull
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    public RoutingStatus getRoutingStatus() {
-        List<String> status = NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sCardEmulationService.getRoutingStatus(), new ArrayList<>());
-        return new RoutingStatus(routeStringToInt(status.get(0)),
-                routeStringToInt(status.get(1)),
-                routeStringToInt(status.get(2)));
-    }
-
-    /**
-     * Overwrites NFC controller routing table, which includes Protocol Route, Technology Route,
-     * and Empty AID Route.
-     *
-     * The parameter set to
-     * {@link ProtocolAndTechnologyRoute#PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}
-     * can be used to keep current values for that entry. At least one route should be overridden
-     * when calling this API, otherwise throw {@link IllegalArgumentException}.
-     *
-     * @param protocol ISO-DEP route destination, where the possible inputs are defined in
-     *                 {@link ProtocolAndTechnologyRoute}.
-     * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs
-     *                   are defined in
-     *                   {@link ProtocolAndTechnologyRoute}
-     * @param emptyAid Zero-length AID route destination, where the possible inputs are defined in
-     *                 {@link ProtocolAndTechnologyRoute}
-     * @param systemCode System Code route destination, where the possible inputs are defined in
-     *                   {@link ProtocolAndTechnologyRoute}
-     */
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public void overwriteRoutingTable(
-            @CardEmulation.ProtocolAndTechnologyRoute int protocol,
-            @CardEmulation.ProtocolAndTechnologyRoute int technology,
-            @CardEmulation.ProtocolAndTechnologyRoute int emptyAid,
-            @CardEmulation.ProtocolAndTechnologyRoute int systemCode) {
-
-        String protocolRoute = routeIntToString(protocol);
-        String technologyRoute = routeIntToString(technology);
-        String emptyAidRoute = routeIntToString(emptyAid);
-        String systemCodeRoute = routeIntToString(systemCode);
-
-        NfcAdapter.callService(() ->
-                NfcAdapter.sCardEmulationService.overwriteRoutingTable(
-                        mContext.getUser().getIdentifier(),
-                        emptyAidRoute,
-                        protocolRoute,
-                        technologyRoute,
-                        systemCodeRoute
-                ));
-    }
-
-    /**
-     * Gets current routing table entries.
-     * @return List of {@link NfcRoutingTableEntry} representing current routing table
-     */
-    @NonNull
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public List<NfcRoutingTableEntry> getRoutingTable() {
-        List<Entry> entryList = NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sService.getRoutingTableEntryList(), null);
-        List<NfcRoutingTableEntry> result = new ArrayList<>();
-        for (Entry entry : entryList) {
-            switch (entry.getType()) {
-                case TYPE_TECHNOLOGY -> result.add(
-                        new RoutingTableTechnologyEntry(entry.getNfceeId(),
-                                RoutingTableTechnologyEntry.techStringToInt(entry.getEntry()),
-                                routeStringToInt(entry.getRoutingType()))
-                );
-                case TYPE_PROTOCOL -> result.add(
-                        new RoutingTableProtocolEntry(entry.getNfceeId(),
-                                RoutingTableProtocolEntry.protocolStringToInt(entry.getEntry()),
-                                routeStringToInt(entry.getRoutingType()))
-                );
-                case TYPE_AID -> result.add(
-                        new RoutingTableAidEntry(entry.getNfceeId(), entry.getEntry(),
-                                routeStringToInt(entry.getRoutingType()))
-                );
-                case TYPE_SYSTEMCODE -> result.add(
-                        new RoutingTableSystemCodeEntry(entry.getNfceeId(),
-                                entry.getEntry().getBytes(StandardCharsets.UTF_8),
-                                routeStringToInt(entry.getRoutingType()))
-                );
-            }
-        }
-        return result;
-    }
-
-    /**
-     * API to force a routing table commit.
-     * @return a {@link StatusCode} to indicate if commit routing succeeded or not
-     */
-    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @CommitRoutingStatusCode
-    public int forceRoutingTableCommit() {
-        return NfcAdapter.callServiceReturn(
-                () -> NfcAdapter.sService.commitRouting(), COMMIT_ROUTING_STATUS_FAILED);
-    }
-
-    private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub {
-
-        @Override
-        public void onTagConnected(boolean connected) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(connected, cb::onTagConnected, ex));
-        }
-
-        @Override
-        public void onCardEmulationActivated(boolean isActivated) throws RemoteException {
-            mCardEmulationActivated = isActivated;
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(isActivated, cb::onCardEmulationActivated, ex));
-        }
-
-        @Override
-        public void onRfFieldActivated(boolean isActivated) throws RemoteException {
-            mRfFieldActivated = isActivated;
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(isActivated, cb::onRfFieldActivated, ex));
-        }
-
-        @Override
-        public void onRfDiscoveryStarted(boolean isDiscoveryStarted) throws RemoteException {
-            mRfDiscoveryStarted = isDiscoveryStarted;
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(isDiscoveryStarted, cb::onRfDiscoveryStarted, ex));
-        }
-
-        @Override
-        public void onEeListenActivated(boolean isActivated) throws RemoteException {
-            mEeListenActivated = isActivated;
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(isActivated, cb::onEeListenActivated, ex));
-        }
-
-        @Override
-        public void onEeUpdated() throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(null, (Object input) -> cb.onEeUpdated(), ex));
-        }
-
-        @Override
-        public void onStateUpdated(int state) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(state, cb::onStateUpdated, ex));
-        }
-
-        @Override
-        public void onApplyRouting(ResultReceiver isSkipped) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                        new ReceiverWrapper<>(isSkipped), cb::onApplyRouting, ex));
-        }
-        @Override
-        public void onNdefRead(ResultReceiver isSkipped) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                        new ReceiverWrapper<>(isSkipped), cb::onNdefRead, ex));
-        }
-        @Override
-        public void onEnable(ResultReceiver isAllowed) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                        new ReceiverWrapper<>(isAllowed), cb::onEnableRequested, ex));
-        }
-        @Override
-        public void onDisable(ResultReceiver isAllowed) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                        new ReceiverWrapper<>(isAllowed), cb::onDisableRequested, ex));
-        }
-        @Override
-        public void onBootStarted() throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(null, (Object input) -> cb.onBootStarted(), ex));
-        }
-        @Override
-        public void onEnableStarted() throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(null, (Object input) -> cb.onEnableStarted(), ex));
-        }
-        @Override
-        public void onDisableStarted() throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(null, (Object input) -> cb.onDisableStarted(), ex));
-        }
-        @Override
-        public void onBootFinished(int status) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(status, cb::onBootFinished, ex));
-        }
-        @Override
-        public void onEnableFinished(int status) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(status, cb::onEnableFinished, ex));
-        }
-        @Override
-        public void onDisableFinished(int status) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(status, cb::onDisableFinished, ex));
-        }
-        @Override
-        public void onTagDispatch(ResultReceiver isSkipped) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                        new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex));
-        }
-        @Override
-        public void onRoutingChanged(ResultReceiver isSkipped) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(
-                            new ReceiverWrapper<>(isSkipped), cb::onRoutingChanged, ex));
-        }
-        @Override
-        public void onHceEventReceived(int action) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(action, cb::onHceEventReceived, ex));
-        }
-
-        @Override
-        public void onReaderOptionChanged(boolean enabled) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(enabled, cb::onReaderOptionChanged, ex));
-        }
-
-        public void onRoutingTableFull() throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(null,
-                            (Object input) -> cb.onRoutingTableFull(), ex));
-        }
-
-        @Override
-        public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer)
-                throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoid2ArgCallback(packages, new ReceiverWrapper<>(intentConsumer),
-                            cb::onGetOemAppSearchIntent, ex));
-        }
-
-        @Override
-        public void onNdefMessage(Tag tag, NdefMessage message,
-                                  ResultReceiver hasOemExecutableContent) throws RemoteException {
-            mCallbackMap.forEach((cb, ex) -> {
-                synchronized (mLock) {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        ex.execute(() -> cb.onNdefMessage(
-                                tag, message, new ReceiverWrapper<>(hasOemExecutableContent)));
-                    } catch (RuntimeException exception) {
-                        throw exception;
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onLaunchHceAppChooserActivity(String selectedAid,
-                                                  List<ApduServiceInfo> services,
-                                                  ComponentName failedComponent, String category)
-                throws RemoteException {
-            mCallbackMap.forEach((cb, ex) -> {
-                synchronized (mLock) {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        ex.execute(() -> cb.onLaunchHceAppChooserActivity(
-                                selectedAid, services, failedComponent, category));
-                    } catch (RuntimeException exception) {
-                        throw exception;
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onLaunchHceTapAgainActivity(ApduServiceInfo service, String category)
-                throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoid2ArgCallback(service, category, cb::onLaunchHceTapAgainDialog, ex));
-        }
-
-        @Override
-        public void onLogEventNotified(OemLogItems item) throws RemoteException  {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoidCallback(item, cb::onLogEventNotified, ex));
-        }
-
-        @Override
-        public void onExtractOemPackages(NdefMessage message, ResultReceiver packageConsumer)
-                throws RemoteException {
-            mCallbackMap.forEach((cb, ex) ->
-                    handleVoid2ArgCallback(message,
-                            new ReceiverWrapper<>(packageConsumer),
-                            cb::onExtractOemPackages, ex));
-        }
-
-        private <T> void handleVoidCallback(
-                T input, Consumer<T> callbackMethod, Executor executor) {
-            synchronized (mLock) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    executor.execute(() -> callbackMethod.accept(input));
-                } catch (RuntimeException ex) {
-                    throw ex;
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        }
-
-        private <T1, T2> void handleVoid2ArgCallback(
-                T1 input1, T2 input2, BiConsumer<T1, T2> callbackMethod, Executor executor) {
-            synchronized (mLock) {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    executor.execute(() -> callbackMethod.accept(input1, input2));
-                } catch (RuntimeException ex) {
-                    throw ex;
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-        }
-
-        private <S, T> S handleNonVoidCallbackWithInput(
-                S defaultValue, T input, Function<T, S> callbackMethod) throws RemoteException {
-            synchronized (mLock) {
-                final long identity = Binder.clearCallingIdentity();
-                S result = defaultValue;
-                try {
-                    ExecutorService executor = Executors.newSingleThreadExecutor();
-                    FutureTask<S> futureTask = new FutureTask<>(() -> callbackMethod.apply(input));
-                    var unused = executor.submit(futureTask);
-                    try {
-                        result = futureTask.get(
-                                OEM_EXTENSION_RESPONSE_THRESHOLD_MS, TimeUnit.MILLISECONDS);
-                    } catch (ExecutionException | InterruptedException e) {
-                        e.printStackTrace();
-                    } catch (TimeoutException e) {
-                        Log.w(TAG, "Callback timed out: " + callbackMethod);
-                        e.printStackTrace();
-                    } finally {
-                        executor.shutdown();
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-                return result;
-            }
-        }
-
-        private <T> T handleNonVoidCallbackWithoutInput(T defaultValue, Supplier<T> callbackMethod)
-                throws RemoteException {
-            synchronized (mLock) {
-                final long identity = Binder.clearCallingIdentity();
-                T result = defaultValue;
-                try {
-                    ExecutorService executor = Executors.newSingleThreadExecutor();
-                    FutureTask<T> futureTask = new FutureTask<>(callbackMethod::get);
-                    var unused = executor.submit(futureTask);
-                    try {
-                        result = futureTask.get(
-                                OEM_EXTENSION_RESPONSE_THRESHOLD_MS, TimeUnit.MILLISECONDS);
-                    } catch (ExecutionException | InterruptedException e) {
-                        e.printStackTrace();
-                    } catch (TimeoutException e) {
-                        Log.w(TAG, "Callback timed out: " + callbackMethod);
-                        e.printStackTrace();
-                    } finally {
-                        executor.shutdown();
-                    }
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-                return result;
-            }
-        }
-    }
-
-    private @CardEmulation.ProtocolAndTechnologyRoute int routeStringToInt(String route) {
-        if (route.equals("DH")) {
-            return PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
-        } else if (route.startsWith("eSE")) {
-            return PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
-        } else if (route.startsWith("SIM")) {
-            return PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
-        } else {
-            throw new IllegalStateException("Unexpected value: " + route);
-        }
-    }
-
-    private class ReceiverWrapper<T> implements Consumer<T> {
-        private final ResultReceiver mResultReceiver;
-
-        ReceiverWrapper(ResultReceiver resultReceiver) {
-            mResultReceiver = resultReceiver;
-        }
-
-        @Override
-        public void accept(T result) {
-            if (result instanceof Boolean) {
-                mResultReceiver.send((Boolean) result ? 1 : 0, null);
-            } else if (result instanceof Intent) {
-                Bundle bundle = new Bundle();
-                bundle.putParcelable("intent", (Intent) result);
-                mResultReceiver.send(0, bundle);
-            } else if (result instanceof List<?> list) {
-                if (list.stream().allMatch(String.class::isInstance)) {
-                    Bundle bundle = new Bundle();
-                    bundle.putStringArray("packageNames",
-                            list.stream().map(pkg -> (String) pkg).toArray(String[]::new));
-                    mResultReceiver.send(0, bundle);
-                }
-            }
-        }
-
-        @Override
-        public Consumer<T> andThen(Consumer<? super T> after) {
-            return Consumer.super.andThen(after);
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/NfcRoutingTableEntry.java b/nfc/java/android/nfc/NfcRoutingTableEntry.java
deleted file mode 100644
index 4153779..0000000
--- a/nfc/java/android/nfc/NfcRoutingTableEntry.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Class to represent an entry of routing table. This class is abstract and extended by
- * {@link RoutingTableTechnologyEntry}, {@link RoutingTableProtocolEntry},
- * {@link RoutingTableAidEntry} and {@link RoutingTableSystemCodeEntry}.
- *
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public abstract class NfcRoutingTableEntry {
-    private final int mNfceeId;
-    private final int mType;
-    private final int mRouteType;
-
-    /**
-     * AID routing table type.
-     */
-    public static final int TYPE_AID = 0;
-    /**
-     * Protocol routing table type.
-     */
-    public static final int TYPE_PROTOCOL = 1;
-    /**
-     * Technology routing table type.
-     */
-    public static final int TYPE_TECHNOLOGY = 2;
-    /**
-     * System Code routing table type.
-     */
-    public static final int TYPE_SYSTEM_CODE = 3;
-
-    /**
-     * Possible type of this routing table entry.
-     * @hide
-     */
-    @IntDef(prefix = "TYPE_", value = {
-            TYPE_AID,
-            TYPE_PROTOCOL,
-            TYPE_TECHNOLOGY,
-            TYPE_SYSTEM_CODE
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface RoutingTableType {}
-
-    /** @hide */
-    protected NfcRoutingTableEntry(int nfceeId, @RoutingTableType int type,
-            @CardEmulation.ProtocolAndTechnologyRoute int routeType) {
-        mNfceeId = nfceeId;
-        mType = type;
-        mRouteType = routeType;
-    }
-
-    /**
-     * Gets the NFCEE Id of this entry.
-     * @return an integer of NFCEE Id.
-     */
-    public int getNfceeId() {
-        return mNfceeId;
-    }
-
-    /**
-     * Get the type of this entry.
-     * @return an integer defined in {@link RoutingTableType}
-     */
-    @RoutingTableType
-    public int getType() {
-        return mType;
-    }
-
-    /**
-     * Get the route type of this entry.
-     * @return an integer defined in
-     * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
-     */
-    @CardEmulation.ProtocolAndTechnologyRoute
-    public int getRouteType() {
-        return mRouteType;
-    }
-}
diff --git a/nfc/java/android/nfc/NfcVendorNciCallbackListener.java b/nfc/java/android/nfc/NfcVendorNciCallbackListener.java
deleted file mode 100644
index 742d75f..0000000
--- a/nfc/java/android/nfc/NfcVendorNciCallbackListener.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.nfc.NfcAdapter.NfcVendorNciCallback;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * @hide
- */
-public final class NfcVendorNciCallbackListener extends INfcVendorNciCallback.Stub {
-    private static final String TAG = "Nfc.NfcVendorNciCallbacks";
-    private final INfcAdapter mAdapter;
-    private boolean mIsRegistered = false;
-    private final Map<NfcVendorNciCallback, Executor> mCallbackMap = new HashMap<>();
-
-    public NfcVendorNciCallbackListener(@NonNull INfcAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    public void register(@NonNull Executor executor, @NonNull NfcVendorNciCallback callback) {
-        synchronized (this) {
-            if (mCallbackMap.containsKey(callback)) {
-                return;
-            }
-            mCallbackMap.put(callback, executor);
-            if (!mIsRegistered) {
-                try {
-                    mAdapter.registerVendorExtensionCallback(this);
-                    mIsRegistered = true;
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to register adapter state callback");
-                    mCallbackMap.remove(callback);
-                    throw e.rethrowFromSystemServer();
-                }
-            }
-        }
-    }
-
-    public void unregister(@NonNull NfcVendorNciCallback callback) {
-        synchronized (this) {
-            if (!mCallbackMap.containsKey(callback) || !mIsRegistered) {
-                return;
-            }
-            if (mCallbackMap.size() == 1) {
-                try {
-                    mAdapter.unregisterVendorExtensionCallback(this);
-                    mIsRegistered = false;
-                    mCallbackMap.remove(callback);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to unregister AdapterStateCallback with service");
-                    throw e.rethrowFromSystemServer();
-                }
-            } else {
-                mCallbackMap.remove(callback);
-            }
-        }
-    }
-
-    @Override
-    public void onVendorResponseReceived(int gid, int oid, @NonNull byte[] payload)
-            throws RemoteException {
-        synchronized (this) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                for (NfcVendorNciCallback callback : mCallbackMap.keySet()) {
-                    Executor executor = mCallbackMap.get(callback);
-                    executor.execute(() -> callback.onVendorNciResponse(gid, oid, payload));
-                }
-            } catch (RuntimeException ex) {
-                throw ex;
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    @Override
-    public void onVendorNotificationReceived(int gid, int oid, @NonNull byte[] payload)
-            throws RemoteException {
-        synchronized (this) {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                for (NfcVendorNciCallback callback : mCallbackMap.keySet()) {
-                    Executor executor = mCallbackMap.get(callback);
-                    executor.execute(() -> callback.onVendorNciNotification(gid, oid, payload));
-                }
-            } catch (RuntimeException ex) {
-                throw ex;
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/NfcWlcStateListener.java b/nfc/java/android/nfc/NfcWlcStateListener.java
deleted file mode 100644
index 890cb09..0000000
--- a/nfc/java/android/nfc/NfcWlcStateListener.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.nfc.NfcAdapter.WlcStateListener;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * @hide
- */
-public class NfcWlcStateListener extends INfcWlcStateListener.Stub {
-    private static final String TAG = NfcWlcStateListener.class.getSimpleName();
-
-    private final INfcAdapter mAdapter;
-
-    private final Map<WlcStateListener, Executor> mListenerMap = new HashMap<>();
-
-    private WlcListenerDeviceInfo mCurrentState = null;
-    private boolean mIsRegistered = false;
-
-    public NfcWlcStateListener(@NonNull INfcAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    /**
-     * Register a {@link WlcStateListener} with this
-     * {@link WlcStateListener}
-     *
-     * @param executor an {@link Executor} to execute given listener
-     * @param listener user implementation of the {@link WlcStateListener}
-     */
-    public void register(@NonNull Executor executor, @NonNull WlcStateListener listener) {
-        synchronized (this) {
-            if (mListenerMap.containsKey(listener)) {
-                return;
-            }
-
-            mListenerMap.put(listener, executor);
-
-            if (!mIsRegistered) {
-                try {
-                    mAdapter.registerWlcStateListener(this);
-                    mIsRegistered = true;
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to register");
-                }
-            }
-        }
-    }
-
-    /**
-     * Unregister the specified {@link WlcStateListener}
-     *
-     * @param listener user implementation of the {@link WlcStateListener}
-     */
-    public void unregister(@NonNull WlcStateListener listener) {
-        synchronized (this) {
-            if (!mListenerMap.containsKey(listener)) {
-                return;
-            }
-
-            mListenerMap.remove(listener);
-
-            if (mListenerMap.isEmpty() && mIsRegistered) {
-                try {
-                    mAdapter.unregisterWlcStateListener(this);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Failed to unregister");
-                }
-                mIsRegistered = false;
-            }
-        }
-    }
-
-    private void sendCurrentState(@NonNull WlcStateListener listener) {
-        synchronized (this) {
-            Executor executor = mListenerMap.get(listener);
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                if (Flags.enableNfcCharging()) {
-                    executor.execute(() -> listener.onWlcStateChanged(
-                            mCurrentState));
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        }
-    }
-
-    @Override
-    public void onWlcStateChanged(@NonNull WlcListenerDeviceInfo wlcListenerDeviceInfo) {
-        synchronized (this) {
-            mCurrentState = wlcListenerDeviceInfo;
-
-            for (WlcStateListener cb : mListenerMap.keySet()) {
-                sendCurrentState(cb);
-            }
-        }
-    }
-}
-
diff --git a/nfc/java/android/nfc/OemLogItems.aidl b/nfc/java/android/nfc/OemLogItems.aidl
deleted file mode 100644
index 3bcb445..0000000
--- a/nfc/java/android/nfc/OemLogItems.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable OemLogItems;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/OemLogItems.java b/nfc/java/android/nfc/OemLogItems.java
deleted file mode 100644
index 4f3e199..0000000
--- a/nfc/java/android/nfc/OemLogItems.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*

- * Copyright 2024 The Android Open Source Project

- *

- * Licensed under the Apache License, Version 2.0 (the "License");

- * you may not use this file except in compliance with the License.

- * You may obtain a copy of the License at

- *

- *      http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing, software

- * distributed under the License is distributed on an "AS IS" BASIS,

- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- * See the License for the specific language governing permissions and

- * limitations under the License.

- */

-

-package android.nfc;

-

-import android.annotation.FlaggedApi;

-import android.annotation.IntDef;

-import android.annotation.NonNull;

-import android.annotation.Nullable;

-import android.annotation.SystemApi;

-import android.os.Parcel;

-import android.os.Parcelable;

-

-import java.lang.annotation.Retention;

-import java.lang.annotation.RetentionPolicy;

-import java.time.Instant;

-

-/**

- * A log class for OEMs to get log information of NFC events.

- * @hide

- */

-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)

-@SystemApi

-public final class OemLogItems implements Parcelable {

-    /**

-     * Used when RF field state is changed.

-     */

-    public static final int LOG_ACTION_RF_FIELD_STATE_CHANGED = 0X01;

-    /**

-     * Used when NFC is toggled. Event should be set to {@link LogEvent#EVENT_ENABLE} or

-     * {@link LogEvent#EVENT_DISABLE} if this action is used.

-     */

-    public static final int LOG_ACTION_NFC_TOGGLE = 0x0201;

-    /**

-     * Used when sending host routing status.

-     */

-    public static final int LOG_ACTION_HCE_DATA = 0x0204;

-    /**

-     * Used when screen state is changed.

-     */

-    public static final int LOG_ACTION_SCREEN_STATE_CHANGED = 0x0206;

-    /**

-     * Used when tag is detected.

-     */

-    public static final int LOG_ACTION_TAG_DETECTED = 0x03;

-

-    /**

-     * @hide

-     */

-    @IntDef(prefix = { "LOG_ACTION_" }, value = {

-            LOG_ACTION_RF_FIELD_STATE_CHANGED,

-            LOG_ACTION_NFC_TOGGLE,

-            LOG_ACTION_HCE_DATA,

-            LOG_ACTION_SCREEN_STATE_CHANGED,

-            LOG_ACTION_TAG_DETECTED,

-    })

-    @Retention(RetentionPolicy.SOURCE)

-    public @interface LogAction {}

-

-    /**

-     * Represents the event is not set.

-     */

-    public static final int EVENT_UNSET = 0;

-    /**

-     * Represents nfc enable is called.

-     */

-    public static final int EVENT_ENABLE = 1;

-    /**

-     * Represents nfc disable is called.

-     */

-    public static final int EVENT_DISABLE = 2;

-    /** @hide */

-    @IntDef(prefix = { "EVENT_" }, value = {

-            EVENT_UNSET,

-            EVENT_ENABLE,

-            EVENT_DISABLE,

-    })

-    @Retention(RetentionPolicy.SOURCE)

-    public @interface LogEvent {}

-    private int mAction;

-    private int mEvent;

-    private int mCallingPid;

-    private byte[] mCommandApdus;

-    private byte[] mResponseApdus;

-    private Instant mRfFieldOnTime;

-    private Tag mTag;

-

-    /** @hide */

-    public OemLogItems(@LogAction int action, @LogEvent int event, int callingPid,

-            byte[] commandApdus, byte[] responseApdus, Instant rfFieldOnTime,

-            Tag tag) {

-        mAction = action;

-        mEvent = event;

-        mTag = tag;

-        mCallingPid = callingPid;

-        mCommandApdus = commandApdus;

-        mResponseApdus = responseApdus;

-        mRfFieldOnTime = rfFieldOnTime;

-    }

-

-    /**

-     * Describe the kinds of special objects contained in this Parcelable

-     * instance's marshaled representation. For example, if the object will

-     * include a file descriptor in the output of {@link #writeToParcel(Parcel, int)},

-     * the return value of this method must include the

-     * {@link #CONTENTS_FILE_DESCRIPTOR} bit.

-     *

-     * @return a bitmask indicating the set of special object types marshaled

-     * by this Parcelable object instance.

-     */

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

-     */

-    @Override

-    public void writeToParcel(@NonNull Parcel dest, int flags) {

-        dest.writeInt(mAction);

-        dest.writeInt(mEvent);

-        dest.writeInt(mCallingPid);

-        dest.writeInt(mCommandApdus.length);

-        dest.writeByteArray(mCommandApdus);

-        dest.writeInt(mResponseApdus.length);

-        dest.writeByteArray(mResponseApdus);

-        dest.writeBoolean(mRfFieldOnTime != null);

-        if (mRfFieldOnTime != null) {

-            dest.writeLong(mRfFieldOnTime.getEpochSecond());

-            dest.writeInt(mRfFieldOnTime.getNano());

-        }

-        dest.writeParcelable(mTag, 0);

-    }

-

-    /** @hide */

-    public static class Builder {

-        private final OemLogItems mItem;

-

-        public Builder(@LogAction int type) {

-            mItem = new OemLogItems(type, EVENT_UNSET, 0, new byte[0], new byte[0], null, null);

-        }

-

-        /** Setter of the log action. */

-        public OemLogItems.Builder setAction(@LogAction int action) {

-            mItem.mAction = action;

-            return this;

-        }

-

-        /** Setter of the log calling event. */

-        public OemLogItems.Builder setCallingEvent(@LogEvent int event) {

-            mItem.mEvent = event;

-            return this;

-        }

-

-        /** Setter of the log calling Pid. */

-        public OemLogItems.Builder setCallingPid(int pid) {

-            mItem.mCallingPid = pid;

-            return this;

-        }

-

-        /** Setter of APDU command. */

-        public OemLogItems.Builder setApduCommand(byte[] apdus) {

-            mItem.mCommandApdus = apdus;

-            return this;

-        }

-

-        /** Setter of RF field on time. */

-        public OemLogItems.Builder setRfFieldOnTime(Instant time) {

-            mItem.mRfFieldOnTime = time;

-            return this;

-        }

-

-        /** Setter of APDU response. */

-        public OemLogItems.Builder setApduResponse(byte[] apdus) {

-            mItem.mResponseApdus = apdus;

-            return this;

-        }

-

-        /** Setter of dispatched tag. */

-        public OemLogItems.Builder setTag(Tag tag) {

-            mItem.mTag = tag;

-            return this;

-        }

-

-        /** Builds an {@link OemLogItems} instance. */

-        public OemLogItems build() {

-            return mItem;

-        }

-    }

-

-    /**

-     * Gets the action of this log.

-     * @return one of {@link LogAction}

-     */

-    @LogAction

-    public int getAction() {

-        return mAction;

-    }

-

-    /**

-     * Gets the event of this log. This will be set to {@link LogEvent#EVENT_ENABLE} or

-     * {@link LogEvent#EVENT_DISABLE} only when action is set to

-     * {@link LogAction#LOG_ACTION_NFC_TOGGLE}

-     * @return one of {@link LogEvent}

-     */

-    @LogEvent

-    public int getEvent() {

-        return mEvent;

-    }

-

-    /**

-     * Gets the calling Pid of this log. This field will be set only when action is set to

-     * {@link LogAction#LOG_ACTION_NFC_TOGGLE}

-     * @return calling Pid

-     */

-    public int getCallingPid() {

-        return mCallingPid;

-    }

-

-    /**

-     * Gets the command APDUs of this log. This field will be set only when action is set to

-     * {@link LogAction#LOG_ACTION_HCE_DATA}

-     * @return a byte array of command APDUs with the same format as

-     * {@link android.nfc.cardemulation.HostApduService#sendResponseApdu(byte[])}

-     */

-    @Nullable

-    public byte[] getCommandApdu() {

-        return mCommandApdus;

-    }

-

-    /**

-     * Gets the response APDUs of this log. This field will be set only when action is set to

-     * {@link LogAction#LOG_ACTION_HCE_DATA}

-     * @return a byte array of response APDUs with the same format as

-     * {@link android.nfc.cardemulation.HostApduService#sendResponseApdu(byte[])}

-     */

-    @Nullable

-    public byte[] getResponseApdu() {

-        return mResponseApdus;

-    }

-

-    /**

-     * Gets the RF field event time in this log in millisecond. This field will be set only when

-     * action is set to {@link LogAction#LOG_ACTION_RF_FIELD_STATE_CHANGED}

-     * @return an {@link Instant} of RF field event time.

-     */

-    @Nullable

-    public Instant getRfFieldEventTimeMillis() {

-        return mRfFieldOnTime;

-    }

-

-    /**

-     * Gets the tag of this log. This field will be set only when action is set to

-     * {@link LogAction#LOG_ACTION_TAG_DETECTED}

-     * @return a detected {@link Tag} in {@link #LOG_ACTION_TAG_DETECTED} case. Return

-     * null otherwise.

-     */

-    @Nullable

-    public Tag getTag() {

-        return mTag;

-    }

-

-    private String byteToHex(byte[] bytes) {

-        char[] HexArray = "0123456789ABCDEF".toCharArray();

-        char[] hexChars = new char[bytes.length * 2];

-        for (int j = 0; j < bytes.length; j++) {

-            int v = bytes[j] & 0xFF;

-            hexChars[j * 2] = HexArray[v >>> 4];

-            hexChars[j * 2 + 1] = HexArray[v & 0x0F];

-        }

-        return new String(hexChars);

-    }

-

-    @Override

-    public String toString() {

-        return "[mCommandApdus: "

-                + ((mCommandApdus != null) ? byteToHex(mCommandApdus) : "null")

-                + "[mResponseApdus: "

-                + ((mResponseApdus != null) ? byteToHex(mResponseApdus) : "null")

-                + ", mCallingApi= " + mEvent

-                + ", mAction= " + mAction

-                + ", mCallingPId = " + mCallingPid

-                + ", mRfFieldOnTime= " + mRfFieldOnTime;

-    }

-    private OemLogItems(Parcel in) {

-        this.mAction = in.readInt();

-        this.mEvent = in.readInt();

-        this.mCallingPid = in.readInt();

-        this.mCommandApdus = new byte[in.readInt()];

-        in.readByteArray(this.mCommandApdus);

-        this.mResponseApdus = new byte[in.readInt()];

-        in.readByteArray(this.mResponseApdus);

-        boolean isRfFieldOnTimeSet = in.readBoolean();

-        if (isRfFieldOnTimeSet) {

-            this.mRfFieldOnTime = Instant.ofEpochSecond(in.readLong(), in.readInt());

-        } else {

-            this.mRfFieldOnTime = null;

-        }

-        this.mTag = in.readParcelable(Tag.class.getClassLoader(), Tag.class);

-    }

-

-    public static final @NonNull Parcelable.Creator<OemLogItems> CREATOR =

-            new Parcelable.Creator<OemLogItems>() {

-                @Override

-                public OemLogItems createFromParcel(Parcel in) {

-                    return new OemLogItems(in);

-                }

-

-                @Override

-                public OemLogItems[] newArray(int size) {

-                    return new OemLogItems[size];

-                }

-            };

-

-}

diff --git a/nfc/java/android/nfc/Placeholder.java b/nfc/java/android/nfc/Placeholder.java
deleted file mode 100644
index 3509644..0000000
--- a/nfc/java/android/nfc/Placeholder.java
+++ /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 android.nfc;
-
-/**
- * Placeholder class so new framework-nfc module isn't empty, will be removed once module is
- * populated.
- *
- * @hide
- *
- */
-public class Placeholder {
-}
diff --git a/nfc/java/android/nfc/RoutingStatus.java b/nfc/java/android/nfc/RoutingStatus.java
deleted file mode 100644
index 4a1b1f3..0000000
--- a/nfc/java/android/nfc/RoutingStatus.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-/**
- * A class indicating default route, ISO-DEP route and off-host route.
- *
- * @hide
- */
-@SystemApi
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-public class RoutingStatus {
-    private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute;
-    private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute;
-    private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute;
-
-    RoutingStatus(@CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute,
-                  @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute,
-                  @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute) {
-        this.mDefaultRoute = mDefaultRoute;
-        this.mDefaultIsoDepRoute = mDefaultIsoDepRoute;
-        this.mDefaultOffHostRoute = mDefaultOffHostRoute;
-    }
-
-    /**
-     * Getter of the default route.
-     * @return an integer defined in
-     * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @CardEmulation.ProtocolAndTechnologyRoute
-    public int getDefaultRoute() {
-        return mDefaultRoute;
-    }
-
-    /**
-     * Getter of the default ISO-DEP route.
-     * @return an integer defined in
-     * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @CardEmulation.ProtocolAndTechnologyRoute
-    public int getDefaultIsoDepRoute() {
-        return mDefaultIsoDepRoute;
-    }
-
-    /**
-     * Getter of the default off-host route.
-     * @return an integer defined in
-     * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @CardEmulation.ProtocolAndTechnologyRoute
-    public int getDefaultOffHostRoute() {
-        return mDefaultOffHostRoute;
-    }
-
-}
diff --git a/nfc/java/android/nfc/RoutingTableAidEntry.java b/nfc/java/android/nfc/RoutingTableAidEntry.java
deleted file mode 100644
index be94f9f..0000000
--- a/nfc/java/android/nfc/RoutingTableAidEntry.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-/**
- * Represents an Application ID (AID) entry in current routing table.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public class RoutingTableAidEntry extends NfcRoutingTableEntry {
-    private final String mValue;
-
-    /** @hide */
-    public RoutingTableAidEntry(int nfceeId, String value,
-            @CardEmulation.ProtocolAndTechnologyRoute int routeType) {
-        super(nfceeId, TYPE_AID, routeType);
-        this.mValue = value;
-    }
-
-    /**
-     * Gets AID value.
-     * @return String of AID
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @NonNull
-    public String getAid() {
-        return mValue;
-    }
-}
diff --git a/nfc/java/android/nfc/RoutingTableProtocolEntry.java b/nfc/java/android/nfc/RoutingTableProtocolEntry.java
deleted file mode 100644
index a68d8c1..0000000
--- a/nfc/java/android/nfc/RoutingTableProtocolEntry.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents a protocol entry in current routing table.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public class RoutingTableProtocolEntry extends NfcRoutingTableEntry {
-    /**
-     * Protocol undetermined.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_UNDETERMINED = 0;
-    /**
-     * T1T Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_T1T = 1;
-    /**
-     * T2T Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_T2T = 2;
-    /**
-     * T3T Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_T3T = 3;
-    /**
-     * ISO-DEP Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_ISO_DEP = 4;
-    /**
-     * DEP Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_NFC_DEP = 5;
-    /**
-     * T5T Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_T5T = 6;
-    /**
-     * NDEF Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_NDEF = 7;
-    /**
-     * Unsupported Protocol
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int PROTOCOL_UNSUPPORTED = -1;
-
-    /**
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "PROTOCOL_" }, value = {
-            PROTOCOL_UNDETERMINED,
-            PROTOCOL_T1T,
-            PROTOCOL_T2T,
-            PROTOCOL_T3T,
-            PROTOCOL_ISO_DEP,
-            PROTOCOL_NFC_DEP,
-            PROTOCOL_T5T,
-            PROTOCOL_NDEF,
-            PROTOCOL_UNSUPPORTED
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ProtocolValue {}
-
-    private final @ProtocolValue int mValue;
-
-    /** @hide */
-    public RoutingTableProtocolEntry(int nfceeId, @ProtocolValue int value,
-            @CardEmulation.ProtocolAndTechnologyRoute int routeType) {
-        super(nfceeId, TYPE_PROTOCOL, routeType);
-        this.mValue = value;
-    }
-
-    /**
-     * Gets Protocol value.
-     * @return Protocol defined in {@link ProtocolValue}
-     */
-    @ProtocolValue
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public int getProtocol() {
-        return mValue;
-    }
-
-    /** @hide */
-    @ProtocolValue
-    public static int protocolStringToInt(String protocolString) {
-        return switch (protocolString) {
-            case "PROTOCOL_T1T" -> PROTOCOL_T1T;
-            case "PROTOCOL_T2T" -> PROTOCOL_T2T;
-            case "PROTOCOL_T3T" -> PROTOCOL_T3T;
-            case "PROTOCOL_ISO_DEP" -> PROTOCOL_ISO_DEP;
-            case "PROTOCOL_NFC_DEP" -> PROTOCOL_NFC_DEP;
-            case "PROTOCOL_T5T" -> PROTOCOL_T5T;
-            case "PROTOCOL_NDEF" -> PROTOCOL_NDEF;
-            case "PROTOCOL_UNDETERMINED" -> PROTOCOL_UNDETERMINED;
-            default -> PROTOCOL_UNSUPPORTED;
-        };
-    }
-}
diff --git a/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java b/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java
deleted file mode 100644
index 06cc0a5..0000000
--- a/nfc/java/android/nfc/RoutingTableSystemCodeEntry.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-/**
- * Represents a system code entry in current routing table, where system codes are two-byte values
- * used in NFC-F technology (a type of NFC communication) to identify specific
- * device configurations.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public class RoutingTableSystemCodeEntry extends NfcRoutingTableEntry {
-    private final byte[] mValue;
-
-    /** @hide */
-    public RoutingTableSystemCodeEntry(int nfceeId, byte[] value,
-            @CardEmulation.ProtocolAndTechnologyRoute int routeType) {
-        super(nfceeId, TYPE_SYSTEM_CODE, routeType);
-        this.mValue = value;
-    }
-
-    /**
-     * Gets system code value.
-     * @return Byte array of system code
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    @NonNull
-    public byte[] getSystemCode() {
-        return mValue;
-    }
-}
diff --git a/nfc/java/android/nfc/RoutingTableTechnologyEntry.java b/nfc/java/android/nfc/RoutingTableTechnologyEntry.java
deleted file mode 100644
index 86239ce..0000000
--- a/nfc/java/android/nfc/RoutingTableTechnologyEntry.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.nfc.cardemulation.CardEmulation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents a technology entry in current routing table.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public class RoutingTableTechnologyEntry extends NfcRoutingTableEntry {
-    /**
-     * Technology-A.
-     * <p>Tech-A is mostly used for payment and ticketing applications. It supports various
-     * Tag platforms including Type 1, Type 2 and Type 4A tags. </p>
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int TECHNOLOGY_A = 0;
-    /**
-     * Technology-B which is based on ISO/IEC 14443-3 standard.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int TECHNOLOGY_B = 1;
-    /**
-     * Technology-F.
-     * <p>Tech-F is a standard which supports Type 3 Tags and NFC-DEP protocol etc.</p>
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int TECHNOLOGY_F = 2;
-    /**
-     * Technology-V.
-     * <p>Tech-V is an NFC technology used for communication with passive tags that operate
-     * at a longer range than other NFC technologies. </p>
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int TECHNOLOGY_V = 3;
-    /**
-     * Unsupported technology
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public static final int TECHNOLOGY_UNSUPPORTED = -1;
-
-    /**
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "TECHNOLOGY_" }, value = {
-            TECHNOLOGY_A,
-            TECHNOLOGY_B,
-            TECHNOLOGY_F,
-            TECHNOLOGY_V,
-            TECHNOLOGY_UNSUPPORTED
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface TechnologyValue{}
-
-    private final @TechnologyValue int mValue;
-
-    /** @hide */
-    public RoutingTableTechnologyEntry(int nfceeId, @TechnologyValue int value,
-            @CardEmulation.ProtocolAndTechnologyRoute int routeType) {
-        super(nfceeId, TYPE_TECHNOLOGY, routeType);
-        this.mValue = value;
-    }
-
-    /**
-     * Gets technology value.
-     * @return technology value
-     */
-    @TechnologyValue
-    @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-    public int getTechnology() {
-        return mValue;
-    }
-
-    /** @hide */
-    @TechnologyValue
-    public static int techStringToInt(String tech) {
-        return switch (tech) {
-            case "TECHNOLOGY_A" -> TECHNOLOGY_A;
-            case "TECHNOLOGY_B" -> TECHNOLOGY_B;
-            case "TECHNOLOGY_F" -> TECHNOLOGY_F;
-            case "TECHNOLOGY_V" -> TECHNOLOGY_V;
-            default -> TECHNOLOGY_UNSUPPORTED;
-        };
-    }
-}
diff --git a/nfc/java/android/nfc/T4tNdefNfcee.java b/nfc/java/android/nfc/T4tNdefNfcee.java
deleted file mode 100644
index 05a30aa..0000000
--- a/nfc/java/android/nfc/T4tNdefNfcee.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.WorkerThread;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * This class is used for performing T4T (Type-4 Tag) NDEF (NFC Data Exchange Format)
- * NFCEE (NFC Execution Environment) operations.
- * This can be used to write NDEF data to emulate a T4T tag in an NFCEE
- * (NFC Execution Environment - eSE, SIM, etc). Refer to the NFC forum specification
- * "NFCForum-TS-NCI-2.3 section 10.4" and "NFCForum-TS-T4T-1.1 section 4.2" for more details.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public final class T4tNdefNfcee {
-    private static final String TAG = "NdefNfcee";
-    static T4tNdefNfcee sNdefNfcee;
-
-    private T4tNdefNfcee() {
-    }
-
-    /**
-     * Helper to get an instance of this class.
-     *
-     * @return
-     * @hide
-     */
-    @NonNull
-    public static T4tNdefNfcee getInstance() {
-        if (sNdefNfcee == null) {
-            sNdefNfcee = new T4tNdefNfcee();
-        }
-        return sNdefNfcee;
-    }
-
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data is successful.
-     */
-    public static final int WRITE_DATA_SUCCESS = 0;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to unknown reasons.
-     */
-    public static final int WRITE_DATA_ERROR_INTERNAL = -1;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to ongoing rf activity.
-     */
-    public static final int WRITE_DATA_ERROR_RF_ACTIVATED = -2;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to Nfc off.
-     */
-    public static final int WRITE_DATA_ERROR_NFC_NOT_ON = -3;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to invalid file id.
-     */
-    public static final int WRITE_DATA_ERROR_INVALID_FILE_ID = -4;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to invalid length.
-     */
-    public static final int WRITE_DATA_ERROR_INVALID_LENGTH = -5;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to core connection create failure.
-     */
-    public static final int WRITE_DATA_ERROR_CONNECTION_FAILED = -6;
-    /**
-     * Return flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to empty payload.
-     */
-    public static final int WRITE_DATA_ERROR_EMPTY_PAYLOAD = -7;
-    /**
-     * Returns flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail due to invalid ndef format.
-     */
-    public static final int WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED = -8;
-    /**
-     * Returns flag for {@link #writeData(int, byte[])}.
-     * It indicates write data fail if a concurrent NDEF NFCEE operation is ongoing.
-     */
-    public static final int WRITE_DATA_ERROR_DEVICE_BUSY = -9;
-
-    /**
-     * Possible return values for {@link #writeData(int, byte[])}.
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "WRITE_DATA_" }, value = {
-        WRITE_DATA_SUCCESS,
-        WRITE_DATA_ERROR_INTERNAL,
-        WRITE_DATA_ERROR_RF_ACTIVATED,
-        WRITE_DATA_ERROR_NFC_NOT_ON,
-        WRITE_DATA_ERROR_INVALID_FILE_ID,
-        WRITE_DATA_ERROR_INVALID_LENGTH,
-        WRITE_DATA_ERROR_CONNECTION_FAILED,
-        WRITE_DATA_ERROR_EMPTY_PAYLOAD,
-        WRITE_DATA_ERROR_NDEF_VALIDATION_FAILED,
-        WRITE_DATA_ERROR_DEVICE_BUSY,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface WriteDataStatus{}
-
-    /**
-     * This API performs writes of T4T data to NFCEE.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread.</p>
-     * <p>Applications must send complete Ndef Message payload, do not need to fragment
-     * the payload, it will be automatically fragmented and defragmented by
-     * {@link #writeData} if it exceeds max message length limits</p>
-     *
-     * @param fileId File id (Refer NFC Forum Type 4 Tag Specification
-     *               Section 4.2 File Identifiers and Access Conditions
-     *               for more information) to which to write.
-     * @param data   This should be valid Ndef Message format.
-     *               Refer to Nfc forum NDEF specification NDEF Message section
-     * @return status of the operation.
-     * @hide
-     */
-    @SystemApi
-    @WorkerThread
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public @WriteDataStatus int writeData(@IntRange(from = 0, to = 65535) int fileId,
-            @NonNull byte[] data) {
-        return NfcAdapter.callServiceReturn(() ->
-                NfcAdapter.sNdefNfceeService.writeData(fileId, data), WRITE_DATA_ERROR_INTERNAL);
-    }
-
-    /**
-     * This API performs reading of T4T content of Nfcee.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread.</p>
-     *
-     * @param fileId File Id (Refer
-     *               Section 4.2 File Identifiers and Access Conditions
-     *               for more information) from which to read.
-     * @return - Returns complete Ndef message if success
-     *           Refer to Nfc forum NDEF specification NDEF Message section
-     * @throws IllegalStateException if read fails because the fileId is invalid
-     *         or if a concurrent operation is in progress.
-     * @hide
-     */
-    @SystemApi
-    @WorkerThread
-    @NonNull
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public byte[] readData(@IntRange(from = 0, to = 65535) int fileId) {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sNdefNfceeService.readData(fileId), null);
-    }
-
-    /**
-     * Return flag for {@link #clearNdefData()}.
-     * It indicates clear data is successful.
-     */
-    public static final int CLEAR_DATA_SUCCESS = 1;
-     /**
-     * Return flag for {@link #clearNdefData()}.
-     * It indicates clear data failed due to internal error while processing the clear.
-     */
-    public static final int CLEAR_DATA_FAILED_INTERNAL = 0;
-    /**
-     * Return flag for {@link #clearNdefData()}.
-     * It indicates clear data failed  if a concurrent NDEF NFCEE operation is ongoing.
-     */
-    public static final int CLEAR_DATA_FAILED_DEVICE_BUSY = -1;
-
-
-    /**
-     * Possible return values for {@link #clearNdefData()}.
-     *
-     * @hide
-     */
-    @IntDef(prefix = { "CLEAR_DATA_" }, value = {
-        CLEAR_DATA_SUCCESS,
-        CLEAR_DATA_FAILED_INTERNAL,
-        CLEAR_DATA_FAILED_DEVICE_BUSY,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ClearDataStatus{}
-
-    /**
-     * This API will set all the T4T NDEF NFCEE data to zero.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread.
-     *
-     * <p>This API can be called regardless of NDEF file lock state.
-     * </p>
-     * @return status of the operation
-     *
-     * @hide
-     */
-    @SystemApi
-    @WorkerThread
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public @ClearDataStatus int clearData() {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sNdefNfceeService.clearNdefData(), CLEAR_DATA_FAILED_INTERNAL);
-    }
-
-    /**
-     * Returns whether NDEF NFCEE operation is ongoing or not.
-     *
-     * @return true if NDEF NFCEE operation is ongoing, else false.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isOperationOngoing() {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sNdefNfceeService.isNdefOperationOngoing(), false);
-    }
-
-    /**
-     * This Api is to check the status of NDEF NFCEE emulation feature is
-     * supported or not.
-     *
-     * @return true if NDEF NFCEE emulation feature is supported, else false.
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    public boolean isSupported() {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sNdefNfceeService.isNdefNfceeEmulationSupported(), false);
-    }
-
-    /**
-     * This API performs reading of T4T NDEF NFCEE CC file content.
-     *
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details.
-     *
-     * @return Returns CC file content if success or null if failed to read.
-     * @throws IllegalStateException if the device is busy.
-     * @hide
-     */
-    @SystemApi
-    @WorkerThread
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @Nullable
-    public T4tNdefNfceeCcFileInfo readCcfile() {
-        return NfcAdapter.callServiceReturn(() ->
-            NfcAdapter.sNdefNfceeService.readCcfile(), null);
-    }
-}
diff --git a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl
deleted file mode 100644
index f72f74e..0000000
--- a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable T4tNdefNfceeCcFileInfo;
-
diff --git a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java b/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java
deleted file mode 100644
index ce67f8f..0000000
--- a/nfc/java/android/nfc/T4tNdefNfceeCcFileInfo.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * This class is used to represence T4T (Type-4 Tag) NDEF (NFC Data Exchange Format)
- * NFCEE (NFC Execution Environment) CC (Capability Container) File data.
- * The CC file stores metadata about the T4T tag being emulated.
- *
- * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details.
- * @hide
- */
-@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
-@SystemApi
-public final class T4tNdefNfceeCcFileInfo implements Parcelable {
-    /**
-     * Indicates the size of this capability container (called “CC File”)<p>
-     */
-    private int mCcLength;
-    /**
-     * Indicates the mapping specification version<p>
-     */
-    private int mVersion;
-    /**
-     * Indicates the NDEF File Identifier<p>
-     */
-    private int mFileId;
-    /**
-     * Indicates the maximum Max NDEF file size<p>
-     */
-    private int mMaxSize;
-    /**
-     * Indicates the read access condition<p>
-     */
-    private boolean mIsReadAllowed;
-    /**
-     * Indicates the write access condition<p>
-     */
-    private boolean mIsWriteAllowed;
-
-    /**
-     * Constructor to be used by NFC service and internal classes.
-     * @hide
-     */
-    public T4tNdefNfceeCcFileInfo(int cclen, int version,
-                      int ndefFileId, int ndefMaxSize,
-                      boolean isReadAllowed, boolean isWriteAllowed) {
-        mCcLength = cclen;
-        mVersion = version;
-        mFileId = ndefFileId;
-        mMaxSize = ndefMaxSize;
-        mIsReadAllowed = isReadAllowed;
-        mIsWriteAllowed = isWriteAllowed;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mCcLength);
-        dest.writeInt(mVersion);
-        dest.writeInt(mFileId);
-        dest.writeInt(mMaxSize);
-        dest.writeBoolean(mIsReadAllowed);
-        dest.writeBoolean(mIsWriteAllowed);
-    }
-
-    /**
-     * Indicates the size of this capability container (called “CC File”).
-     *
-     * @return length of the CC file.
-     */
-    @IntRange(from = 0xf, to = 0x7fff)
-    public int getCcFileLength() {
-        return mCcLength;
-    }
-
-    /**
-     * T4T tag mapping version 2.0.
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details.
-     */
-    public static final int VERSION_2_0 = 0x20;
-    /**
-     * T4T tag mapping version 2.0.
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.4" for more details.
-     */
-    public static final int VERSION_3_0 = 0x30;
-
-    /**
-     * Possible return values for {@link #getVersion()}.
-     * @hide
-     */
-    @IntDef(prefix = { "VERSION_" }, value = {
-            VERSION_2_0,
-            VERSION_3_0,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Version{}
-
-    /**
-     * Indicates the mapping version of the T4T tag supported.
-     *
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.5" for more details.
-     *
-     * @return version of the specification
-     */
-    @Version
-    public int getVersion() {
-        return mVersion;
-    }
-
-    /**
-     * Indicates the NDEF File Identifier. This is the identifier used in the last invocation of
-     * {@link T4tNdefNfcee#writeData(int, byte[])}
-     *
-     * @return FileId of the data stored or -1 if no data is present.
-     */
-    @IntRange(from = -1, to = 65535)
-    public int getFileId() {
-        return mFileId;
-    }
-
-    /**
-     * Indicates the maximum size of T4T NDEF data that can be written to the NFCEE.
-     *
-     * @return max size of the contents.
-     */
-    @IntRange(from = 0x5, to = 0x7fff)
-    public int getMaxSize() {
-        return mMaxSize;
-    }
-
-    /**
-     * Indicates the read access condition.
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details.
-     * @return boolean true if read access is allowed, otherwise false.
-     */
-    public boolean isReadAllowed() {
-        return mIsReadAllowed;
-    }
-
-    /**
-     * Indicates the write access condition.
-     * Refer to the NFC forum specification "NFCForum-TS-T4T-1.1 section 4.2" for more details.
-     * @return boolean if write access is allowed, otherwise false.
-     */
-    public boolean isWriteAllowed() {
-        return mIsWriteAllowed;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final @NonNull Parcelable.Creator<T4tNdefNfceeCcFileInfo> CREATOR =
-            new Parcelable.Creator<>() {
-                @Override
-                public T4tNdefNfceeCcFileInfo createFromParcel(Parcel in) {
-
-                    // NdefNfceeCcFileInfo fields
-                    int cclen = in.readInt();
-                    int version = in.readInt();
-                    int ndefFileId = in.readInt();
-                    int ndefMaxSize = in.readInt();
-                    boolean isReadAllowed = in.readBoolean();
-                    boolean isWriteAllowed = in.readBoolean();
-
-                    return new T4tNdefNfceeCcFileInfo(cclen, version,
-                            ndefFileId, ndefMaxSize,
-                            isReadAllowed, isWriteAllowed);
-                }
-
-                @Override
-                public T4tNdefNfceeCcFileInfo[] newArray(int size) {
-                    return new T4tNdefNfceeCcFileInfo[size];
-                }
-            };
-}
diff --git a/nfc/java/android/nfc/Tag.aidl b/nfc/java/android/nfc/Tag.aidl
deleted file mode 100644
index 312261e..0000000
--- a/nfc/java/android/nfc/Tag.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable Tag;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/Tag.java b/nfc/java/android/nfc/Tag.java
deleted file mode 100644
index 500038f..0000000
--- a/nfc/java/android/nfc/Tag.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.nfc.tech.IsoDep;
-import android.nfc.tech.MifareClassic;
-import android.nfc.tech.MifareUltralight;
-import android.nfc.tech.Ndef;
-import android.nfc.tech.NdefFormatable;
-import android.nfc.tech.NfcA;
-import android.nfc.tech.NfcB;
-import android.nfc.tech.NfcBarcode;
-import android.nfc.tech.NfcF;
-import android.nfc.tech.NfcV;
-import android.nfc.tech.TagTechnology;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashMap;
-
-/**
- * Represents an NFC tag that has been discovered.
- * <p>
- * {@link Tag} is an immutable object that represents the state of a NFC tag at
- * the time of discovery. It can be used as a handle to {@link TagTechnology} classes
- * to perform advanced operations, or directly queried for its ID via {@link #getId} and the
- * set of technologies it contains via {@link #getTechList}. Arrays passed to and
- * returned by this class are <em>not</em> cloned, so be careful not to modify them.
- * <p>
- * A new tag object is created every time a tag is discovered (comes into range), even
- * if it is the same physical tag. If a tag is removed and then returned into range, then
- * only the most recent tag object can be successfully used to create a {@link TagTechnology}.
- *
- * <h3>Tag Dispatch</h3>
- * When a tag is discovered, a {@link Tag} object is created and passed to a
- * single activity via the {@link NfcAdapter#EXTRA_TAG} extra in an
- * {@link android.content.Intent} via {@link Context#startActivity}. A four stage dispatch is used
- * to select the
- * most appropriate activity to handle the tag. The Android OS executes each stage in order,
- * and completes dispatch as soon as a single matching activity is found. If there are multiple
- * matching activities found at any one stage then the Android activity chooser dialog is shown
- * to allow the user to select the activity to receive the tag.
- *
- * <p>The Tag dispatch mechanism was designed to give a high probability of dispatching
- * a tag to the correct activity without showing the user an activity chooser dialog.
- * This is important for NFC interactions because they are very transient -- if a user has to
- * move the Android device to choose an application then the connection will likely be broken.
- *
- * <h4>1. Foreground activity dispatch</h4>
- * A foreground activity that has called
- * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} is
- * given priority. See the documentation on
- * {@link NfcAdapter#enableForegroundDispatch NfcAdapter.enableForegroundDispatch()} for
- * its usage.
- * <h4>2. NDEF data dispatch</h4>
- * If the tag contains NDEF data the system inspects the first {@link NdefRecord} in the first
- * {@link NdefMessage}. If the record is a URI, SmartPoster, or MIME data
- * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_NDEF_DISCOVERED}. For URI
- * and SmartPoster records the URI is put into the intent's data field. For MIME records the MIME
- * type is put in the intent's type field. This allows activities to register to be launched only
- * when data they know how to handle is present on a tag. This is the preferred method of handling
- * data on a tag since NDEF data can be stored on many types of tags and doesn't depend on a
- * specific tag technology. 
- * See {@link NfcAdapter#ACTION_NDEF_DISCOVERED} for more detail. If the tag does not contain
- * NDEF data, or if no activity is registered
- * for {@link NfcAdapter#ACTION_NDEF_DISCOVERED} with a matching data URI or MIME type then dispatch
- * moves to stage 3.
- * <h4>3. Tag Technology dispatch</h4>
- * {@link Context#startActivity} is called with {@link NfcAdapter#ACTION_TECH_DISCOVERED} to
- * dispatch the tag to an activity that can handle the technologies present on the tag.
- * Technologies are defined as sub-classes of {@link TagTechnology}, see the package
- * {@link android.nfc.tech}. The Android OS looks for an activity that can handle one or
- * more technologies in the tag. See {@link NfcAdapter#ACTION_TECH_DISCOVERED} for more detail.
- * <h4>4. Fall-back dispatch</h4>
- * If no activity has been matched then {@link Context#startActivity} is called with
- * {@link NfcAdapter#ACTION_TAG_DISCOVERED}. This is intended as a fall-back mechanism.
- * See {@link NfcAdapter#ACTION_TAG_DISCOVERED}.
- *
- * <h3>NFC Tag Background</h3>
- * An NFC tag is a passive NFC device, powered by the NFC field of this Android device while
- * it is in range. Tag's can come in many forms, such as stickers, cards, key fobs, or
- * even embedded in a more sophisticated device.
- * <p>
- * Tags can have a wide range of capabilities. Simple tags just offer read/write semantics,
- * and contain some one time
- * programmable areas to make read-only. More complex tags offer math operations
- * and per-sector access control and authentication. The most sophisticated tags
- * contain operating environments allowing complex interactions with the
- * code executing on the tag. Use {@link TagTechnology} classes to access a broad
- * range of capabilities available in NFC tags.
- * <p>
- */
-public final class Tag implements Parcelable {
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    final byte[] mId;
-    final int[] mTechList;
-    final String[] mTechStringList;
-    final Bundle[] mTechExtras;
-    final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
-    final long mCookie;        // for accessibility checking
-    final INfcTag mTagService; // interface to NFC service, will be null if mock tag
-
-    int mConnectedTechnology;
-
-    /**
-     * Hidden constructor to be used by NFC service and internal classes.
-     * @hide
-     */
-    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
-            long cookie, INfcTag tagService) {
-        if (techList == null) {
-            throw new IllegalArgumentException("rawTargets cannot be null");
-        }
-        mId = id;
-        mTechList = Arrays.copyOf(techList, techList.length);
-        mTechStringList = generateTechStringList(techList);
-        // Ensure mTechExtras is as long as mTechList
-        mTechExtras = Arrays.copyOf(techListExtras, techList.length);
-        mServiceHandle = serviceHandle;
-        mCookie = cookie;
-        mTagService = tagService;
-        mConnectedTechnology = -1;
-
-        if (tagService == null) {
-            return;
-        }
-    }
-
-    /**
-     * Construct a mock Tag.
-     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
-     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
-     * <p>This constructor might be useful for mock testing.
-     * @param id The tag identifier, can be null
-     * @param techList must not be null
-     * @return freshly constructed tag
-     * @hide
-     */
-    public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras,
-            long cookie) {
-        // set serviceHandle to 0 and tagService to null to indicate mock tag
-        return new Tag(id, techList, techListExtras, 0, cookie, null);
-    }
-
-    private String[] generateTechStringList(int[] techList) {
-        final int size = techList.length;
-        String[] strings = new String[size];
-        for (int i = 0; i < size; i++) {
-            switch (techList[i]) {
-                case TagTechnology.ISO_DEP:
-                    strings[i] = IsoDep.class.getName();
-                    break;
-                case TagTechnology.MIFARE_CLASSIC:
-                    strings[i] = MifareClassic.class.getName();
-                    break;
-                case TagTechnology.MIFARE_ULTRALIGHT:
-                    strings[i] = MifareUltralight.class.getName();
-                    break;
-                case TagTechnology.NDEF:
-                    strings[i] = Ndef.class.getName();
-                    break;
-                case TagTechnology.NDEF_FORMATABLE:
-                    strings[i] = NdefFormatable.class.getName();
-                    break;
-                case TagTechnology.NFC_A:
-                    strings[i] = NfcA.class.getName();
-                    break;
-                case TagTechnology.NFC_B:
-                    strings[i] = NfcB.class.getName();
-                    break;
-                case TagTechnology.NFC_F:
-                    strings[i] = NfcF.class.getName();
-                    break;
-                case TagTechnology.NFC_V:
-                    strings[i] = NfcV.class.getName();
-                    break;
-                case TagTechnology.NFC_BARCODE:
-                    strings[i] = NfcBarcode.class.getName();
-                    break;
-                default:
-                    throw new IllegalArgumentException("Unknown tech type " + techList[i]);
-            }
-        }
-        return strings;
-    }
-
-    static int[] getTechCodesFromStrings(String[] techStringList) throws IllegalArgumentException {
-        if (techStringList == null) {
-            throw new IllegalArgumentException("List cannot be null");
-        }
-        int[] techIntList = new int[techStringList.length];
-        HashMap<String, Integer> stringToCodeMap = getTechStringToCodeMap();
-        for (int i = 0; i < techStringList.length; i++) {
-            Integer code = stringToCodeMap.get(techStringList[i]);
-
-            if (code == null) {
-                throw new IllegalArgumentException("Unknown tech type " + techStringList[i]);
-            }
-
-            techIntList[i] = code.intValue();
-        }
-        return techIntList;
-    }
-
-    private static HashMap<String, Integer> getTechStringToCodeMap() {
-        HashMap<String, Integer> techStringToCodeMap = new HashMap<String, Integer>();
-
-        techStringToCodeMap.put(IsoDep.class.getName(), TagTechnology.ISO_DEP);
-        techStringToCodeMap.put(MifareClassic.class.getName(), TagTechnology.MIFARE_CLASSIC);
-        techStringToCodeMap.put(MifareUltralight.class.getName(), TagTechnology.MIFARE_ULTRALIGHT);
-        techStringToCodeMap.put(Ndef.class.getName(), TagTechnology.NDEF);
-        techStringToCodeMap.put(NdefFormatable.class.getName(), TagTechnology.NDEF_FORMATABLE);
-        techStringToCodeMap.put(NfcA.class.getName(), TagTechnology.NFC_A);
-        techStringToCodeMap.put(NfcB.class.getName(), TagTechnology.NFC_B);
-        techStringToCodeMap.put(NfcF.class.getName(), TagTechnology.NFC_F);
-        techStringToCodeMap.put(NfcV.class.getName(), TagTechnology.NFC_V);
-        techStringToCodeMap.put(NfcBarcode.class.getName(), TagTechnology.NFC_BARCODE);
-
-        return techStringToCodeMap;
-    }
-
-    /**
-     * For use by NfcService only.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public int getServiceHandle() {
-        return mServiceHandle;
-    }
-
-    /**
-     * For use by NfcService only.
-     * @hide
-     */
-    public int[] getTechCodeList() {
-        return mTechList;
-    }
-
-    /**
-     * Get the Tag Identifier (if it has one).
-     * <p>The tag identifier is a low level serial number, used for anti-collision
-     * and identification.
-     * <p> Most tags have a stable unique identifier
-     * (UID), but some tags will generate a random ID every time they are discovered
-     * (RID), and there are some tags with no ID at all (the byte array will be zero-sized).
-     * <p> The size and format of an ID is specific to the RF technology used by the tag.
-     * <p> This function retrieves the ID as determined at discovery time, and does not
-     * perform any further RF communication or block.
-     * @return ID as byte array, never null
-     */
-    public byte[] getId() {
-        return mId;
-    }
-
-    /**
-     * Get the technologies available in this tag, as fully qualified class names.
-     * <p>
-     * A technology is an implementation of the {@link TagTechnology} interface,
-     * and can be instantiated by calling the static <code>get(Tag)</code>
-     * method on the implementation with this Tag. The {@link TagTechnology}
-     * object can then be used to perform advanced, technology-specific operations on a tag.
-     * <p>
-     * Android defines a mandatory set of technologies that must be correctly
-     * enumerated by all Android NFC devices, and an optional
-     * set of proprietary technologies.
-     * See {@link TagTechnology} for more details.
-     * <p>
-     * The ordering of the returned array is undefined and should not be relied upon.
-     * @return an array of fully-qualified {@link TagTechnology} class-names.
-     */
-    public String[] getTechList() {
-        return mTechStringList;
-    }
-
-    /**
-     * Rediscover the technologies available on this tag.
-     * <p>
-     * The technologies that are available on a tag may change due to
-     * operations being performed on a tag. For example, formatting a
-     * tag as NDEF adds the {@link Ndef} technology. The {@link rediscover}
-     * method reenumerates the available technologies on the tag
-     * and returns a new {@link Tag} object containing these technologies.
-     * <p>
-     * You may not be connected to any of this {@link Tag}'s technologies
-     * when calling this method.
-     * This method guarantees that you will be returned the same Tag
-     * if it is still in the field.
-     * <p>May cause RF activity and may block. Must not be called
-     * from the main application thread. A blocked call will be canceled with
-     * {@link IOException} by calling {@link #close} from another thread.
-     * <p>Does not remove power from the RF field, so a tag having a random
-     * ID should not change its ID.
-     * @return the rediscovered tag object.
-     * @throws IOException if the tag cannot be rediscovered
-     * @hide
-     */
-    // TODO See if we need TagLostException
-    // TODO Unhide for ICS
-    // TODO Update documentation to make sure it matches with the final
-    //      implementation.
-    public Tag rediscover() throws IOException {
-        if (getConnectedTechnology() != -1) {
-            throw new IllegalStateException("Close connection to the technology first!");
-        }
-
-        if (mTagService == null) {
-            throw new IOException("Mock tags don't support this operation.");
-        }
-        try {
-            Tag newTag = mTagService.rediscover(getServiceHandle());
-            if (newTag != null) {
-                return newTag;
-            } else {
-                throw new IOException("Failed to rediscover tag");
-            }
-        } catch (RemoteException e) {
-            throw new IOException("NFC service dead");
-        }
-    }
-
-
-    /** @hide */
-    public boolean hasTech(int techType) {
-        for (int tech : mTechList) {
-            if (tech == techType) return true;
-        }
-        return false;
-    }
-
-    /** @hide */
-    public Bundle getTechExtras(int tech) {
-        int pos = -1;
-        for (int idx = 0; idx < mTechList.length; idx++) {
-          if (mTechList[idx] == tech) {
-              pos = idx;
-              break;
-          }
-        }
-        if (pos < 0) {
-            return null;
-        }
-
-        return mTechExtras[pos];
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public INfcTag getTagService() {
-        if (mTagService == null) {
-            return null;
-        }
-
-        try {
-            if (!mTagService.isTagUpToDate(mCookie)) {
-                String id_str = "";
-                for (int i = 0; i < mId.length; i++) {
-                    id_str = id_str + String.format("%02X ", mId[i]);
-                }
-                String msg = "Permission Denial: Tag ( ID: " + id_str + ") is out of date";
-                throw new SecurityException(msg);
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowAsRuntimeException();
-        }
-        return mTagService;
-    }
-
-    /**
-     * Human-readable description of the tag, for debugging.
-     */
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("TAG: Tech [");
-        String[] techList = getTechList();
-        int length = techList.length;
-        for (int i = 0; i < length; i++) {
-            sb.append(techList[i]);
-            if (i < length - 1) {
-                sb.append(", ");
-            }
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-
-    /*package*/ static byte[] readBytesWithNull(Parcel in) {
-        int len = in.readInt();
-        byte[] result = null;
-        if (len >= 0) {
-            result = new byte[len];
-            in.readByteArray(result);
-        }
-        return result;
-    }
-
-    /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
-        if (b == null) {
-            out.writeInt(-1);
-            return;
-        }
-        out.writeInt(b.length);
-        out.writeByteArray(b);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        // Null mTagService means this is a mock tag
-        int isMock = (mTagService == null)?1:0;
-
-        writeBytesWithNull(dest, mId);
-        dest.writeInt(mTechList.length);
-        dest.writeIntArray(mTechList);
-        dest.writeTypedArray(mTechExtras, 0);
-        dest.writeInt(mServiceHandle);
-        dest.writeLong(mCookie);
-        dest.writeInt(isMock);
-        if (isMock == 0) {
-            dest.writeStrongBinder(mTagService.asBinder());
-        }
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<Tag> CREATOR =
-            new Parcelable.Creator<Tag>() {
-        @Override
-        public Tag createFromParcel(Parcel in) {
-            INfcTag tagService;
-
-            // Tag fields
-            byte[] id = Tag.readBytesWithNull(in);
-            int[] techList = new int[in.readInt()];
-            in.readIntArray(techList);
-            Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
-            int serviceHandle = in.readInt();
-            long cookie = in.readLong();
-            int isMock = in.readInt();
-            if (isMock == 0) {
-                tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
-            }
-            else {
-                tagService = null;
-            }
-
-            return new Tag(id, techList, techExtras, serviceHandle, cookie, tagService);
-        }
-
-        @Override
-        public Tag[] newArray(int size) {
-            return new Tag[size];
-        }
-    };
-
-    /**
-     * For internal use only.
-     *
-     * @hide
-     */
-    public synchronized boolean setConnectedTechnology(int technology) {
-        if (mConnectedTechnology != -1) {
-            return false;
-        }
-        mConnectedTechnology = technology;
-        return true;
-    }
-
-    /**
-     * For internal use only.
-     *
-     * @hide
-     */
-    public int getConnectedTechnology() {
-        return mConnectedTechnology;
-    }
-
-    /**
-     * For internal use only.
-     *
-     * @hide
-     */
-    public void setTechnologyDisconnected() {
-        mConnectedTechnology = -1;
-    }
-}
diff --git a/nfc/java/android/nfc/TagLostException.java b/nfc/java/android/nfc/TagLostException.java
deleted file mode 100644
index 1981d7c..0000000
--- a/nfc/java/android/nfc/TagLostException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import java.io.IOException;
-
-public class TagLostException extends IOException {
-    public TagLostException() {
-        super();
-    }
-
-    public TagLostException(String message) {
-        super(message);
-    }
-}
diff --git a/nfc/java/android/nfc/TechListParcel.aidl b/nfc/java/android/nfc/TechListParcel.aidl
deleted file mode 100644
index 92e646f..0000000
--- a/nfc/java/android/nfc/TechListParcel.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable TechListParcel;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/TechListParcel.java b/nfc/java/android/nfc/TechListParcel.java
deleted file mode 100644
index 9f01559..0000000
--- a/nfc/java/android/nfc/TechListParcel.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.nfc;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public class TechListParcel implements Parcelable {
-
-    private String[][] mTechLists;
-
-    public TechListParcel(String[]... strings) {
-        mTechLists = strings;
-    }
-
-    public String[][] getTechLists() {
-        return mTechLists;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        int count = mTechLists.length;
-        dest.writeInt(count);
-        for (int i = 0; i < count; i++) {
-            String[] techList = mTechLists[i];
-            dest.writeStringArray(techList);
-        }
-    }
-
-    public static final @android.annotation.NonNull Creator<TechListParcel> CREATOR = new Creator<TechListParcel>() {
-        @Override
-        public TechListParcel createFromParcel(Parcel source) {
-            int count = source.readInt();
-            String[][] techLists = new String[count][];
-            for (int i = 0; i < count; i++) {
-                techLists[i] = source.createStringArray();
-            }
-            return new TechListParcel(techLists);
-        }
-
-        @Override
-        public TechListParcel[] newArray(int size) {
-            return new TechListParcel[size];
-        }
-    };
-}
diff --git a/nfc/java/android/nfc/TransceiveResult.aidl b/nfc/java/android/nfc/TransceiveResult.aidl
deleted file mode 100644
index 98f92ee..0000000
--- a/nfc/java/android/nfc/TransceiveResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable TransceiveResult;
diff --git a/nfc/java/android/nfc/TransceiveResult.java b/nfc/java/android/nfc/TransceiveResult.java
deleted file mode 100644
index 7992094..0000000
--- a/nfc/java/android/nfc/TransceiveResult.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2011, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.IOException;
-
-/**
- * Class used to pipe transceive result from the NFC service.
- *
- * @hide
- */
-public final class TransceiveResult implements Parcelable {
-    public static final int RESULT_SUCCESS = 0;
-    public static final int RESULT_FAILURE = 1;
-    public static final int RESULT_TAGLOST = 2;
-    public static final int RESULT_EXCEEDED_LENGTH = 3;
-
-    final int mResult;
-    final byte[] mResponseData;
-
-    public TransceiveResult(final int result, final byte[] data) {
-        mResult = result;
-        mResponseData = data;
-    }
-
-    public byte[] getResponseOrThrow() throws IOException {
-        switch (mResult) {
-            case RESULT_SUCCESS:
-                return mResponseData;
-            case RESULT_TAGLOST:
-                throw new TagLostException("Tag was lost.");
-            case RESULT_EXCEEDED_LENGTH:
-                throw new IOException("Transceive length exceeds supported maximum");
-            default:
-                throw new IOException("Transceive failed");
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mResult);
-        if (mResult == RESULT_SUCCESS) {
-            dest.writeInt(mResponseData.length);
-            dest.writeByteArray(mResponseData);
-        }
-    }
-
-    public static final @android.annotation.NonNull Parcelable.Creator<TransceiveResult> CREATOR =
-            new Parcelable.Creator<TransceiveResult>() {
-        @Override
-        public TransceiveResult createFromParcel(Parcel in) {
-            int result = in.readInt();
-            byte[] responseData;
-
-            if (result == RESULT_SUCCESS) {
-                int responseLength = in.readInt();
-                responseData = new byte[responseLength];
-                in.readByteArray(responseData);
-            } else {
-                responseData = null;
-            }
-            return new TransceiveResult(result, responseData);
-        }
-
-        @Override
-        public TransceiveResult[] newArray(int size) {
-            return new TransceiveResult[size];
-        }
-    };
-
-}
diff --git a/nfc/java/android/nfc/WlcListenerDeviceInfo.aidl b/nfc/java/android/nfc/WlcListenerDeviceInfo.aidl
deleted file mode 100644
index 7f2ca54..0000000
--- a/nfc/java/android/nfc/WlcListenerDeviceInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-parcelable WlcListenerDeviceInfo;
diff --git a/nfc/java/android/nfc/WlcListenerDeviceInfo.java b/nfc/java/android/nfc/WlcListenerDeviceInfo.java
deleted file mode 100644
index 45315f8..0000000
--- a/nfc/java/android/nfc/WlcListenerDeviceInfo.java
+++ /dev/null
@@ -1,145 +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.nfc;
-
-import android.annotation.FlaggedApi;
-import android.annotation.FloatRange;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Contains information of the nfc wireless charging listener device information.
- */
-@FlaggedApi(Flags.FLAG_ENABLE_NFC_CHARGING)
-public final class WlcListenerDeviceInfo implements Parcelable {
-    /**
-     * Device is currently not connected with any WlcListenerDevice.
-     */
-    public static final int STATE_DISCONNECTED = 1;
-
-    /**
-     * Device is currently connected with a WlcListenerDevice and is charging it.
-     */
-    public static final int STATE_CONNECTED_CHARGING = 2;
-
-    /**
-     * Device is currently connected with a WlcListenerDevice without charging it.
-     */
-    public static final int STATE_CONNECTED_DISCHARGING = 3;
-
-    /**
-     * Possible states from {@link #getState}.
-     * @hide
-     */
-    @IntDef(prefix = { "STATE_" }, value = {
-            STATE_DISCONNECTED,
-            STATE_CONNECTED_CHARGING,
-            STATE_CONNECTED_DISCHARGING
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface WlcListenerState{}
-
-    private int mProductId;
-    private double mTemperature;
-    private double mBatteryLevel;
-    private int mState;
-
-     /**
-     * Create a new object containing wlc listener information.
-     *
-     * @param productId code for the device vendor
-     * @param temperature current temperature
-     * @param batteryLevel current battery level
-     * @param state current state
-     */
-    public WlcListenerDeviceInfo(int productId, double temperature, double batteryLevel,
-            @WlcListenerState int state) {
-        this.mProductId = productId;
-        this.mTemperature = temperature;
-        this.mBatteryLevel = batteryLevel;
-        this.mState = state;
-    }
-
-    /**
-     * ProductId of the WLC listener device.
-     * @return integer that is converted from USI Stylus VendorID[11:0].
-     */
-    public int getProductId() {
-        return mProductId;
-    }
-
-    /**
-     * Temperature of the WLC listener device.
-     * @return the value represents the temperature in °C.
-     */
-    public double getTemperature() {
-        return mTemperature;
-    }
-
-    /**
-     * BatteryLevel of the WLC listener device.
-     * @return battery level in percentage [0-100]
-     */
-    public @FloatRange(from = 0.0, to = 100.0) double getBatteryLevel() {
-        return mBatteryLevel;
-    }
-
-    /**
-     * State of the WLC listener device.
-     */
-    public @WlcListenerState int getState() {
-        return mState;
-    }
-
-    private WlcListenerDeviceInfo(Parcel in) {
-        this.mProductId = in.readInt();
-        this.mTemperature = in.readDouble();
-        this.mBatteryLevel = in.readDouble();
-        this.mState = in.readInt();
-    }
-
-    public static final @NonNull Parcelable.Creator<WlcListenerDeviceInfo> CREATOR =
-            new Parcelable.Creator<WlcListenerDeviceInfo>() {
-                @Override
-                public WlcListenerDeviceInfo createFromParcel(Parcel in) {
-                    return new WlcListenerDeviceInfo(in);
-                }
-
-                @Override
-                public WlcListenerDeviceInfo[] newArray(int size) {
-                    return new WlcListenerDeviceInfo[size];
-                }
-            };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mProductId);
-        dest.writeDouble(mTemperature);
-        dest.writeDouble(mBatteryLevel);
-        dest.writeInt(mState);
-    }
-}
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
deleted file mode 100644
index fee9c5b..0000000
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ /dev/null
@@ -1,1497 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-import android.Manifest;
-import android.annotation.CallbackExecutor;
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
-import android.annotation.RequiresPermission;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SystemApi;
-import android.annotation.UserHandleAware;
-import android.annotation.UserIdInt;
-import android.app.Activity;
-import android.app.role.RoleManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.nfc.ComponentNameAndUser;
-import android.nfc.Constants;
-import android.nfc.Flags;
-import android.nfc.INfcCardEmulation;
-import android.nfc.INfcEventCallback;
-import android.nfc.NfcAdapter;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.telephony.SubscriptionManager;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
-import java.util.HexFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.regex.Pattern;
-
-/**
- * This class can be used to query the state of
- * NFC card emulation services.
- *
- * For a general introduction into NFC card emulation,
- * please read the <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html">
- * NFC card emulation developer guide</a>.</p>
- *
- * <p class="note">Use of this class requires the
- * {@link PackageManager#FEATURE_NFC_HOST_CARD_EMULATION} to be present
- * on the device.
- */
-public final class CardEmulation {
-    private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
-    private static final Pattern PLPF_PATTERN = Pattern.compile("[0-9A-Fa-f,\\?,\\*\\.]*");
-
-    static final String TAG = "CardEmulation";
-
-    /**
-     * Activity action: ask the user to change the default
-     * card emulation service for a certain category. This will
-     * show a dialog that asks the user whether they want to
-     * replace the current default service with the service
-     * identified with the ComponentName specified in
-     * {@link #EXTRA_SERVICE_COMPONENT}, for the category
-     * specified in {@link #EXTRA_CATEGORY}. There is an optional
-     * extra field using {@link Intent#EXTRA_USER} to specify
-     * the {@link UserHandle} of the user that owns the app.
-     *
-     * @deprecated Please use {@link android.app.role.RoleManager#createRequestRoleIntent(String)}
-     * with {@link android.app.role.RoleManager#ROLE_WALLET} parameter
-     * and {@link Activity#startActivityForResult(Intent, int)} instead.
-     */
-    @Deprecated
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_CHANGE_DEFAULT =
-            "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
-
-    /**
-     * The category extra for {@link #ACTION_CHANGE_DEFAULT}.
-     *
-     * @see #ACTION_CHANGE_DEFAULT
-     */
-    public static final String EXTRA_CATEGORY = "category";
-
-    /**
-     * The service {@link ComponentName} object passed in as an
-     * extra for {@link #ACTION_CHANGE_DEFAULT}.
-     *
-     * @see #ACTION_CHANGE_DEFAULT
-     */
-    public static final String EXTRA_SERVICE_COMPONENT = "component";
-
-    /**
-     * Category used for NFC payment services.
-     */
-    public static final String CATEGORY_PAYMENT = "payment";
-
-    /**
-     * Category that can be used for all other card emulation
-     * services.
-     */
-    public static final String CATEGORY_OTHER = "other";
-
-    /**
-     * Return value for {@link #getSelectionModeForCategory(String)}.
-     *
-     * <p>In this mode, the user has set a default service for this
-     *    category.
-     *
-     * <p>When using ISO-DEP card emulation with {@link HostApduService}
-     *    or {@link OffHostApduService}, if a remote NFC device selects
-     *    any of the Application IDs (AIDs)
-     *    that the default service has registered in this category,
-     *    that service will automatically be bound to to handle
-     *    the transaction.
-     */
-    public static final int SELECTION_MODE_PREFER_DEFAULT = 0;
-
-    /**
-     * Return value for {@link #getSelectionModeForCategory(String)}.
-     *
-     * <p>In this mode, when using ISO-DEP card emulation with {@link HostApduService}
-     *    or {@link OffHostApduService}, whenever an Application ID (AID) of this category
-     *    is selected, the user is asked which service they want to use to handle
-     *    the transaction, even if there is only one matching service.
-     */
-    public static final int SELECTION_MODE_ALWAYS_ASK = 1;
-
-    /**
-     * Return value for {@link #getSelectionModeForCategory(String)}.
-     *
-     * <p>In this mode, when using ISO-DEP card emulation with {@link HostApduService}
-     *    or {@link OffHostApduService}, the user will only be asked to select a service
-     *    if the Application ID (AID) selected by the reader has been registered by multiple
-     *    services. If there is only one service that has registered for the AID,
-     *    that service will be invoked directly.
-     */
-    public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
-    /**
-     * Route to Device Host (DH).
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0;
-    /**
-     * Route to eSE.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1;
-    /**
-     * Route to UICC.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2;
-
-    /**
-     * Route to the default value in config file.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3;
-
-    /**
-     * Route unset.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET = -1;
-
-    /**
-     * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * succeeded.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    public static final int SET_SERVICE_ENABLED_STATUS_OK = 0;
-
-    /**
-     * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * failed due to the unsupported feature.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1;
-
-    /**
-     * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * failed due to the invalid service.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2;
-
-    /**
-     * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * failed due to the service is already set to the requested status.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3;
-
-    /**
-     * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * failed due to unknown error.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4;
-
-    /**
-     * Status code returned by {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)}
-     * @hide
-     */
-    @IntDef(prefix = "SET_SERVICE_ENABLED_STATUS_", value = {
-            SET_SERVICE_ENABLED_STATUS_OK,
-            SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED,
-            SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE,
-            SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET,
-            SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SetServiceEnabledStatusCode {}
-
-    /**
-     * Property name used to indicate that an application wants to allow associated services
-     * to share the same AID routing priority when this application is the role holder.
-     * <p>
-     * Example:
-     * <pre>
-     *     {@code
-     *     <application>
-     *       ...
-     *       <property android:name="android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY"
-     *         android:value="true"/>
-     *     </application>
-     *     }
-     * </pre>
-     */
-    @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)
-    public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY =
-            "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY";
-
-    static boolean sIsInitialized = false;
-    static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>();
-    static INfcCardEmulation sService;
-
-    final Context mContext;
-
-    private CardEmulation(Context context, INfcCardEmulation service) {
-        mContext = context.getApplicationContext();
-        sService = service;
-    }
-
-    /**
-     * Helper to get an instance of this class.
-     *
-     * @param adapter A reference to an NfcAdapter object.
-     * @return
-     */
-    public static synchronized CardEmulation getInstance(NfcAdapter adapter) {
-        if (adapter == null) throw new NullPointerException("NfcAdapter is null");
-        Context context = adapter.getContext();
-        if (context == null) {
-            Log.e(TAG, "NfcAdapter context is null.");
-            throw new UnsupportedOperationException();
-        }
-        if (!sIsInitialized) {
-            PackageManager pm = context.getPackageManager();
-            if (pm == null) {
-                Log.e(TAG, "Cannot get PackageManager");
-                throw new UnsupportedOperationException();
-            }
-            if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
-                Log.e(TAG, "This device does not support card emulation");
-                throw new UnsupportedOperationException();
-            }
-            sIsInitialized = true;
-        }
-        CardEmulation manager = sCardEmus.get(context);
-        if (manager == null) {
-            // Get card emu service
-            INfcCardEmulation service = adapter.getCardEmulationService();
-            if (service == null) {
-                Log.e(TAG, "This device does not implement the INfcCardEmulation interface.");
-                throw new UnsupportedOperationException();
-            }
-            manager = new CardEmulation(context, service);
-            sCardEmus.put(context, manager);
-        }
-        return manager;
-    }
-
-    /**
-     * Allows an application to query whether a service is currently
-     * the default service to handle a card emulation category.
-     *
-     * <p>Note that if {@link #getSelectionModeForCategory(String)}
-     * returns {@link #SELECTION_MODE_ALWAYS_ASK} or {@link #SELECTION_MODE_ASK_IF_CONFLICT},
-     * this method will always return false. That is because in these
-     * selection modes a default can't be set at the category level. For categories where
-     * the selection mode is {@link #SELECTION_MODE_ALWAYS_ASK} or
-     * {@link #SELECTION_MODE_ASK_IF_CONFLICT}, use
-     * {@link #isDefaultServiceForAid(ComponentName, String)} to determine whether a service
-     * is the default for a specific AID.
-     *
-     * @param service The ComponentName of the service
-     * @param category The category
-     * @return whether service is currently the default service for the category.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     */
-    public boolean isDefaultServiceForCategory(ComponentName service, String category) {
-        return callServiceReturn(() ->
-            sService.isDefaultServiceForCategory(
-                mContext.getUser().getIdentifier(), service, category), false);
-    }
-
-    /**
-     *
-     * Allows an application to query whether a service is currently
-     * the default handler for a specified ISO7816-4 Application ID.
-     *
-     * @param service The ComponentName of the service
-     * @param aid The ISO7816-4 Application ID
-     * @return whether the service is the default handler for the specified AID
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     */
-    public boolean isDefaultServiceForAid(ComponentName service, String aid) {
-        return callServiceReturn(() ->
-            sService.isDefaultServiceForAid(
-                mContext.getUser().getIdentifier(), service, aid), false);
-    }
-
-    /**
-     * <p>
-     * Returns whether the user has allowed AIDs registered in the
-     * specified category to be handled by a service that is preferred
-     * by the foreground application, instead of by a pre-configured default.
-     *
-     * Foreground applications can set such preferences using the
-     * {@link #setPreferredService(Activity, ComponentName)} method.
-     * <p class="note">
-     * Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, this method will always
-     * return true.
-     *
-     * @param category The category, e.g. {@link #CATEGORY_PAYMENT}
-     * @return whether AIDs in the category can be handled by a service
-     *         specified by the foreground app.
-     */
-    @SuppressWarnings("NonUserGetterCalled")
-    public boolean categoryAllowsForegroundPreference(String category) {
-        Context contextAsUser = mContext.createContextAsUser(
-                UserHandle.of(UserHandle.myUserId()), 0);
-
-        RoleManager roleManager = contextAsUser.getSystemService(RoleManager.class);
-        if (roleManager.isRoleAvailable(RoleManager.ROLE_WALLET)) {
-            return true;
-        }
-
-        if (CATEGORY_PAYMENT.equals(category)) {
-            boolean preferForeground = false;
-            try {
-                preferForeground = Settings.Secure.getInt(
-                        contextAsUser.getContentResolver(),
-                        Constants.SETTINGS_SECURE_NFC_PAYMENT_FOREGROUND) != 0;
-            } catch (SettingNotFoundException e) {
-            }
-            return preferForeground;
-        } else {
-            // Allowed for all other categories
-            return true;
-        }
-    }
-
-    /**
-     * Returns the service selection mode for the passed in category.
-     * Valid return values are:
-     * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
-     *    service for this category, which will be preferred.
-     * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked
-     *    every time what service they would like to use in this category.
-     * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked
-     *    to pick a service if there is a conflict.
-     *
-     * <p class="note">
-     * Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, the default service defined
-     * by the holder of {@link android.app.role.RoleManager#ROLE_WALLET} and is category agnostic.
-     *
-     * @param category The category, for example {@link #CATEGORY_PAYMENT}
-     * @return the selection mode for the passed in category
-     */
-    public int getSelectionModeForCategory(String category) {
-        if (CATEGORY_PAYMENT.equals(category)) {
-            boolean paymentRegistered = callServiceReturn(() ->
-                    sService.isDefaultPaymentRegistered(), false);
-            if (paymentRegistered) {
-                return SELECTION_MODE_PREFER_DEFAULT;
-            } else {
-                return SELECTION_MODE_ALWAYS_ASK;
-            }
-        } else {
-            return SELECTION_MODE_ASK_IF_CONFLICT;
-        }
-    }
-    /**
-     * Sets whether when this service becomes the preferred service, if the NFC stack
-     * should enable observe mode or disable observe mode. The default is to not enable observe
-     * mode when a service either the foreground default service or the default payment service so
-     * not calling this method will preserve that behavior.
-     *
-     * @param service The component name of the service
-     * @param enable Whether the service should default to observe mode or not
-     * @return whether the change was successful.
-     */
-    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
-    public boolean setShouldDefaultToObserveModeForService(@NonNull ComponentName service,
-            boolean enable) {
-        return callServiceReturn(() ->
-            sService.setShouldDefaultToObserveModeForService(
-                mContext.getUser().getIdentifier(), service, enable), false);
-    }
-
-    /**
-     * Register a polling loop filter (PLF) for a HostApduService and indicate whether it should
-     * auto-transact or not.  The PLF can be sequence of an
-     * even number of at least 2 hexadecimal numbers (0-9, A-F or a-f), representing a series of
-     * bytes. When non-standard polling loop frame matches this sequence exactly, it may be
-     * delivered to {@link HostApduService#processPollingFrames(List)}.  If auto-transact
-     * is set to true and this service is currently preferred or there are no other services
-     * registered for this filter then observe mode will also be disabled.
-     * @param service The HostApduService to register the filter for
-     * @param pollingLoopFilter The filter to register
-     * @param autoTransact true to have the NFC stack automatically disable observe mode and allow
-     *         transactions to proceed when this filter matches, false otherwise
-     * @return true if the filter was registered, false otherwise
-     * @throws IllegalArgumentException if the passed in string doesn't parse to at least one byte
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public boolean registerPollingLoopFilterForService(@NonNull ComponentName service,
-            @NonNull String pollingLoopFilter, boolean autoTransact) {
-        final String pollingLoopFilterV = validatePollingLoopFilter(pollingLoopFilter);
-        return callServiceReturn(() ->
-            sService.registerPollingLoopFilterForService(
-                mContext.getUser().getIdentifier(), service, pollingLoopFilterV, autoTransact),
-            false);
-    }
-
-    /**
-     * Unregister a polling loop filter (PLF) for a HostApduService. If the PLF had previously been
-     * registered via {@link #registerPollingLoopFilterForService(ComponentName, String, boolean)}
-     * for this service it will be removed.
-     * @param service The HostApduService to unregister the filter for
-     * @param pollingLoopFilter The filter to unregister
-     * @return true if the filter was removed, false otherwise
-     * @throws IllegalArgumentException if the passed in string doesn't parse to at least one byte
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public boolean removePollingLoopFilterForService(@NonNull ComponentName service,
-            @NonNull String pollingLoopFilter) {
-        final String pollingLoopFilterV = validatePollingLoopFilter(pollingLoopFilter);
-        return callServiceReturn(() ->
-            sService.removePollingLoopFilterForService(
-                mContext.getUser().getIdentifier(), service, pollingLoopFilterV), false);
-    }
-
-
-    /**
-     * Register a polling loop pattern filter (PLPF) for a HostApduService and indicate whether it
-     * should auto-transact or not. The pattern may include the characters 0-9 and A-F as well as
-     * the regular expression operators `.`, `?` and `*`. When the beginning of anon-standard
-     * polling loop frame matches this sequence exactly, it may be delivered to
-     * {@link HostApduService#processPollingFrames(List)}. If auto-transact is set to true and this
-     * service is currently preferred or there are no other services registered for this filter
-     * then observe mode will also be disabled.
-     * @param service The HostApduService to register the filter for
-     * @param pollingLoopPatternFilter The pattern filter to register, must to be compatible with
-     *         {@link java.util.regex.Pattern#compile(String)} and only contain hexadecimal numbers
-     *         and `.`, `?` and `*` operators
-     * @param autoTransact true to have the NFC stack automatically disable observe mode and allow
-     *         transactions to proceed when this filter matches, false otherwise
-     * @return true if the filter was registered, false otherwise
-     * @throws IllegalArgumentException if the filter containst elements other than hexadecimal
-     *         numbers and `.`, `?` and `*` operators
-     * @throws java.util.regex.PatternSyntaxException if the regex syntax is invalid
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public boolean registerPollingLoopPatternFilterForService(@NonNull ComponentName service,
-            @NonNull String pollingLoopPatternFilter, boolean autoTransact) {
-        final String pollingLoopPatternFilterV =
-            validatePollingLoopPatternFilter(pollingLoopPatternFilter);
-        return callServiceReturn(() ->
-            sService.registerPollingLoopPatternFilterForService(
-                mContext.getUser().getIdentifier(), service, pollingLoopPatternFilterV,
-                autoTransact),
-            false);
-    }
-
-    /**
-     * Unregister a polling loop pattern filter (PLPF) for a HostApduService. If the PLF had
-     * previously been registered via
-     * {@link #registerPollingLoopFilterForService(ComponentName, String, boolean)} for this
-     * service it will be removed.
-     * @param service The HostApduService to unregister the filter for
-     * @param pollingLoopPatternFilter The filter to unregister, must to be compatible with
-     *         {@link java.util.regex.Pattern#compile(String)} and only contain hexadecimal numbers
-     *         and`.`, `?` and `*` operators
-     * @return true if the filter was removed, false otherwise
-     * @throws IllegalArgumentException if the filter containst elements other than hexadecimal
-     *         numbers and `.`, `?` and `*` operators
-     * @throws java.util.regex.PatternSyntaxException if the regex syntax is invalid
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public boolean removePollingLoopPatternFilterForService(@NonNull ComponentName service,
-            @NonNull String pollingLoopPatternFilter) {
-        final String pollingLoopPatternFilterV =
-            validatePollingLoopPatternFilter(pollingLoopPatternFilter);
-        return callServiceReturn(() ->
-            sService.removePollingLoopPatternFilterForService(
-                mContext.getUser().getIdentifier(), service, pollingLoopPatternFilterV), false);
-    }
-
-    /**
-     * Registers a list of AIDs for a specific category for the
-     * specified service.
-     *
-     * <p>If a list of AIDs for that category was previously
-     * registered for this service (either statically
-     * through the manifest, or dynamically by using this API),
-     * that list of AIDs will be replaced with this one.
-     *
-     * <p>Note that you can only register AIDs for a service that
-     * is running under the same UID as the caller of this API. Typically
-     * this means you need to call this from the same
-     * package as the service itself, though UIDs can also
-     * be shared between packages using shared UIDs.
-     *
-     * @param service The component name of the service
-     * @param category The category of AIDs to be registered
-     * @param aids A list containing the AIDs to be registered
-     * @return whether the registration was successful.
-     */
-    public boolean registerAidsForService(ComponentName service, String category,
-            List<String> aids) {
-        final AidGroup aidGroup = new AidGroup(aids, category);
-        return callServiceReturn(() ->
-            sService.registerAidGroupForService(
-                mContext.getUser().getIdentifier(), service, aidGroup), false);
-    }
-
-    /**
-     * Unsets the off-host Secure Element for the given service.
-     *
-     * <p>Note that this will only remove Secure Element that was dynamically
-     * set using the {@link #setOffHostForService(ComponentName, String)}
-     * and resets it to a value that was statically assigned using manifest.
-     *
-     * <p>Note that you can only unset off-host SE for a service that
-     * is running under the same UID as the caller of this API. Typically
-     * this means you need to call this from the same
-     * package as the service itself, though UIDs can also
-     * be shared between packages using shared UIDs.
-     *
-     * @param service The component name of the service
-     * @return whether the registration was successful.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC)
-    @NonNull
-    public boolean unsetOffHostForService(@NonNull ComponentName service) {
-        return callServiceReturn(() ->
-            sService.unsetOffHostForService(
-                mContext.getUser().getIdentifier(), service), false);
-    }
-
-    /**
-     * Sets the off-host Secure Element for the given service.
-     *
-     * <p>If off-host SE was initially set (either statically
-     * through the manifest, or dynamically by using this API),
-     * it will be replaced with this one. All AIDs registered by
-     * this service will be re-routed to this Secure Element if
-     * successful. AIDs that was statically assigned using manifest
-     * will re-route to off-host SE that stated in manifest after NFC
-     * toggle.
-     *
-     * <p>Note that you can only set off-host SE for a service that
-     * is running under the same UID as the caller of this API. Typically
-     * this means you need to call this from the same
-     * package as the service itself, though UIDs can also
-     * be shared between packages using shared UIDs.
-     *
-     * <p>Registeration will be successful only if the Secure Element
-     * exists on the device.
-     *
-     * @param service The component name of the service
-     * @param offHostSecureElement Secure Element to register the AID to. Only accept strings with
-     *                             prefix SIM or prefix eSE.
-     *                             Ref: GSMA TS.26 - NFC Handset Requirements
-     *                             TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be
-     *                                               SIM[smartcard slot]
-     *                                               (e.g. SIM/SIM1, SIM2… SIMn).
-     *                             TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be
-     *                                               eSE[number]
-     *                                               (e.g. eSE/eSE1, eSE2, etc.).
-     * @return whether the registration was successful.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC)
-    @NonNull
-    public boolean setOffHostForService(@NonNull ComponentName service,
-            @NonNull String offHostSecureElement) {
-        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
-        if (adapter == null || offHostSecureElement == null) {
-            return false;
-        }
-
-        List<String> validSE = adapter.getSupportedOffHostSecureElements();
-        if ((offHostSecureElement.startsWith("eSE") && !validSE.contains("eSE"))
-                || (offHostSecureElement.startsWith("SIM") && !validSE.contains("SIM"))) {
-            return false;
-        }
-
-        if (!offHostSecureElement.startsWith("eSE") && !offHostSecureElement.startsWith("SIM")) {
-            return false;
-        }
-
-        if (offHostSecureElement.equals("eSE")) {
-            offHostSecureElement = "eSE1";
-        } else if (offHostSecureElement.equals("SIM")) {
-            offHostSecureElement = "SIM1";
-        }
-        final String offHostSecureElementV = new String(offHostSecureElement);
-        return callServiceReturn(() ->
-            sService.setOffHostForService(
-                mContext.getUser().getIdentifier(), service, offHostSecureElementV), false);
-    }
-
-    /**
-     * Retrieves the currently registered AIDs for the specified
-     * category for a service.
-     *
-     * <p>Note that this will only return AIDs that were dynamically
-     * registered using {@link #registerAidsForService(ComponentName, String, List)}
-     * method. It will *not* return AIDs that were statically registered
-     * in the manifest.
-     *
-     * @param service The component name of the service
-     * @param category The category for which the AIDs were registered,
-     *                 e.g. {@link #CATEGORY_PAYMENT}
-     * @return The list of AIDs registered for this category, or null if it couldn't be found.
-     */
-    public List<String> getAidsForService(ComponentName service, String category) {
-        AidGroup group = callServiceReturn(() ->
-               sService.getAidGroupForService(
-                   mContext.getUser().getIdentifier(), service, category), null);
-        return (group != null ? group.getAids() : null);
-    }
-
-    /**
-     * Removes a previously registered list of AIDs for the specified category for the
-     * service provided.
-     *
-     * <p>Note that this will only remove AIDs that were dynamically
-     * registered using the {@link #registerAidsForService(ComponentName, String, List)}
-     * method. It will *not* remove AIDs that were statically registered in
-     * the manifest. If dynamically registered AIDs are removed using
-     * this method, and a statically registered AID group for the same category
-     * exists in the manifest, the static AID group will become active again.
-     *
-     * @param service The component name of the service
-     * @param category The category of the AIDs to be removed, e.g. {@link #CATEGORY_PAYMENT}
-     * @return whether the group was successfully removed.
-     */
-    public boolean removeAidsForService(ComponentName service, String category) {
-        return callServiceReturn(() ->
-            sService.removeAidGroupForService(
-                mContext.getUser().getIdentifier(), service, category), false);
-    }
-
-    /**
-     * Allows a foreground application to specify which card emulation service
-     * should be preferred while a specific Activity is in the foreground.
-     *
-     * <p>The specified Activity must currently be in resumed state. A good
-     * paradigm is to call this method in your {@link Activity#onResume}, and to call
-     * {@link #unsetPreferredService(Activity)} in your {@link Activity#onPause}.
-     *
-     * <p>This method call will fail in two specific scenarios:
-     * <ul>
-     * <li> If the service registers one or more AIDs in the {@link #CATEGORY_PAYMENT}
-     * category, but the user has indicated that foreground apps are not allowed
-     * to override the default payment service.
-     * <li> If the service registers one or more AIDs in the {@link #CATEGORY_OTHER}
-     * category that are also handled by the default payment service, and the
-     * user has indicated that foreground apps are not allowed to override the
-     * default payment service.
-     * </ul>
-     *
-     * <p> Use {@link #categoryAllowsForegroundPreference(String)} to determine
-     * whether foreground apps can override the default payment service.
-     *
-     * <p>Note that this preference is not persisted by the OS, and hence must be
-     * called every time the Activity is resumed.
-     *
-     * @param activity The activity which prefers this service to be invoked
-     * @param service The service to be preferred while this activity is in the foreground
-     * @return whether the registration was successful
-     */
-    public boolean setPreferredService(Activity activity, ComponentName service) {
-        // Verify the activity is in the foreground before calling into NfcService
-        if (activity == null || service == null) {
-            throw new NullPointerException("activity or service or category is null");
-        }
-        return callServiceReturn(() -> sService.setPreferredService(service), false);
-    }
-
-    /**
-     * Unsets the preferred service for the specified Activity.
-     *
-     * <p>Note that the specified Activity must still be in resumed
-     * state at the time of this call. A good place to call this method
-     * is in your {@link Activity#onPause} implementation.
-     *
-     * @param activity The activity which the service was registered for
-     * @return true when successful
-     */
-    public boolean unsetPreferredService(Activity activity) {
-        if (activity == null) {
-            throw new NullPointerException("activity is null");
-        }
-        return callServiceReturn(() -> sService.unsetPreferredService(), false);
-    }
-
-    /**
-     * Some devices may allow an application to register all
-     * AIDs that starts with a certain prefix, e.g.
-     * "A000000004*" to register all MasterCard AIDs.
-     *
-     * Use this method to determine whether this device
-     * supports registering AID prefixes.
-     *
-     * @return whether AID prefix registering is supported on this device.
-     */
-    public boolean supportsAidPrefixRegistration() {
-        return callServiceReturn(() -> sService.supportsAidPrefixRegistration(), false);
-    }
-
-    /**
-     * Retrieves the registered AIDs for the preferred payment service.
-     *
-     * @return The list of AIDs registered for this category, or null if it couldn't be found.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
-    @Nullable
-    public List<String> getAidsForPreferredPaymentService() {
-        ApduServiceInfo serviceInfo = callServiceReturn(() ->
-                sService.getPreferredPaymentService(mContext.getUser().getIdentifier()), null);
-        return (serviceInfo != null ? serviceInfo.getAids() : null);
-    }
-
-    /**
-     * Retrieves the route destination for the preferred payment service.
-     *
-     * <p class="note">
-     * Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, the preferred payment service
-     * no longer exists and is replaced by {@link android.app.role.RoleManager#ROLE_WALLET}. This
-     * will return the route for one of the services registered by the role holder (if any). If
-     * there are multiple services registered, it is unspecified which of those will be used to
-     * determine the route.
-     *
-     * @return The route destination secure element name of the preferred payment service.
-     *         HCE payment: "Host"
-     *         OffHost payment: 1. String with prefix SIM or prefix eSE string.
-     *                             Ref: GSMA TS.26 - NFC Handset Requirements
-     *                             TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be
-     *                                               SIM[smartcard slot]
-     *                                               (e.g. SIM/SIM1, SIM2… SIMn).
-     *                             TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be
-     *                                               eSE[number]
-     *                                               (e.g. eSE/eSE1, eSE2, etc.).
-     *                          2. "OffHost" if the payment service does not specify secure element
-     *                             name.
-     */
-    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
-    @Nullable
-    public String getRouteDestinationForPreferredPaymentService() {
-        ApduServiceInfo serviceInfo = callServiceReturn(() ->
-                sService.getPreferredPaymentService(mContext.getUser().getIdentifier()), null);
-        if (serviceInfo != null) {
-            if (!serviceInfo.isOnHost()) {
-                return serviceInfo.getOffHostSecureElement() == null ?
-                        "OffHost" : serviceInfo.getOffHostSecureElement();
-            }
-            return "Host";
-        }
-        return null;
-    }
-
-    /**
-     * Returns a user-visible description of the preferred payment service.
-     *
-     * <p class="note">
-     * Starting with {@link Build.VERSION_CODES#VANILLA_ICE_CREAM}, the preferred payment service
-     * no longer exists and is replaced by {@link android.app.role.RoleManager#ROLE_WALLET}. This
-     * will return the description for one of the services registered by the role holder (if any).
-     * If there are multiple services registered, it is unspecified which of those will be used
-     * to obtain the service description here.
-     *
-     * @return the preferred payment service description
-     */
-    @RequiresPermission(Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
-    @Nullable
-    public CharSequence getDescriptionForPreferredPaymentService() {
-        ApduServiceInfo serviceInfo = callServiceReturn(() ->
-                sService.getPreferredPaymentService(mContext.getUser().getIdentifier()), null);
-        return (serviceInfo != null ? serviceInfo.getDescription() : null);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean setDefaultServiceForCategory(ComponentName service, String category) {
-        return callServiceReturn(() ->
-                sService.setDefaultServiceForCategory(
-                    mContext.getUser().getIdentifier(), service, category), false);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean setDefaultForNextTap(ComponentName service) {
-        return callServiceReturn(() ->
-                sService.setDefaultForNextTap(
-                    mContext.getUser().getIdentifier(), service), false);
-    }
-
-    /**
-     * @hide
-     */
-    public boolean setDefaultForNextTap(int userId, ComponentName service) {
-        return callServiceReturn(() ->
-                sService.setDefaultForNextTap(userId, service), false);
-    }
-
-    /**
-     * @hide
-     */
-    public List<ApduServiceInfo> getServices(String category) {
-        return callServiceReturn(() ->
-                sService.getServices(
-                    mContext.getUser().getIdentifier(), category), null);
-    }
-
-    /**
-     * Retrieves list of services registered of the provided category for the provided user.
-     *
-     * @param category Category string, one of {@link #CATEGORY_PAYMENT} or {@link #CATEGORY_OTHER}
-     * @param userId the user handle of the user whose information is being requested.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-    @NonNull
-    public List<ApduServiceInfo> getServices(@NonNull String category, @UserIdInt int userId) {
-        return callServiceReturn(() ->
-                sService.getServices(userId, category), null);
-    }
-
-    /**
-     * Tests the validity of the polling loop filter.
-     * @param pollingLoopFilter The polling loop filter to test.
-     *
-     * @hide
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static @NonNull String validatePollingLoopFilter(@NonNull String pollingLoopFilter) {
-        // Verify hex characters
-        byte[] plfBytes = HexFormat.of().parseHex(pollingLoopFilter);
-        if (plfBytes.length == 0) {
-            throw new IllegalArgumentException(
-                "Polling loop filter must contain at least one byte.");
-        }
-        return HexFormat.of().withUpperCase().formatHex(plfBytes);
-    }
-
-    /**
-     * Tests the validity of the polling loop pattern filter.
-     * @param pollingLoopPatternFilter The polling loop filter to test.
-     *
-     * @hide
-     */
-    @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static @NonNull String validatePollingLoopPatternFilter(
-        @NonNull String pollingLoopPatternFilter) {
-        // Verify hex characters
-        if (!PLPF_PATTERN.matcher(pollingLoopPatternFilter).matches()) {
-            throw new IllegalArgumentException(
-                "Polling loop pattern filters may only contain hexadecimal numbers, ?s and *s");
-        }
-        return Pattern.compile(pollingLoopPatternFilter.toUpperCase(Locale.ROOT)).toString();
-    }
-
-    /**
-     * A valid AID according to ISO/IEC 7816-4:
-     * <ul>
-     * <li>Has >= 5 bytes and <=16 bytes (>=10 hex chars and <= 32 hex chars)
-     * <li>Consist of only hex characters
-     * <li>Additionally, we allow an asterisk at the end, to indicate
-     *     a prefix
-     * <li>Additinally we allow an (#) at symbol at the end, to indicate
-     *     a subset
-     * </ul>
-     *
-     * @hide
-     */
-    public 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;
-    }
-
-    /**
-     * Allows to set or unset preferred service (category other) to avoid AID Collision. The user
-     * should use corresponding context using {@link Context#createContextAsUser(UserHandle, int)}
-     *
-     * @param service The ComponentName of the service
-     * @param status  true to enable, false to disable
-     * @return status code defined in {@link SetServiceEnabledStatusCode}
-     *
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @SetServiceEnabledStatusCode
-    public int setServiceEnabledForCategoryOther(@NonNull ComponentName service,
-            boolean status) {
-        return callServiceReturn(() ->
-                sService.setServiceEnabledForCategoryOther(mContext.getUser().getIdentifier(),
-                        service, status), SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR);
-    }
-
-    /** @hide */
-    @IntDef(prefix = "PROTOCOL_AND_TECHNOLOGY_ROUTE_",
-            value = {
-                    PROTOCOL_AND_TECHNOLOGY_ROUTE_DH,
-                    PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE,
-                    PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC,
-                    PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET,
-                    PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ProtocolAndTechnologyRoute {}
-
-    /**
-     * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
-     * while this Activity is in the foreground.
-     *
-     * The parameter set to {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}
-     * can be used to keep current values for that entry. Either
-     * Protocol Route or Technology Route should be override when calling this API, otherwise
-     * throw {@link IllegalArgumentException}.
-     * <p>
-     * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
-     * <pre>
-     * protected void onResume() {
-     *     mNfcAdapter.overrideRoutingTable(
-     *         this, {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE},
-     *         {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET});
-     * }</pre>
-     * </p>
-     * Also activities must call {@link #recoverRoutingTable(Activity)}
-     * when it goes to the background. Only the package of the
-     * currently preferred service (the service set as preferred by the current foreground
-     * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the
-     * current Default Wallet Role Holder {@link RoleManager#ROLE_WALLET}),
-     * otherwise a call to this method will fail and throw {@link SecurityException}.
-     * @param activity The Activity that requests NFC controller routing table to be changed.
-     * @param protocol ISO-DEP route destination, where the possible inputs are defined
-     *                 in {@link ProtocolAndTechnologyRoute}.
-     * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs
-     *                   are defined in {@link ProtocolAndTechnologyRoute}
-     * @throws SecurityException if the caller is not the preferred NFC service
-     * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the
-     * foreground.
-     * <p>
-     * This is a high risk API and only included to support mainline effort
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public void overrideRoutingTable(
-            @NonNull Activity activity, @ProtocolAndTechnologyRoute int protocol,
-            @ProtocolAndTechnologyRoute int technology) {
-        if (!activity.isResumed()) {
-            throw new IllegalArgumentException("Activity must be resumed.");
-        }
-        String protocolRoute = routeIntToString(protocol);
-        String technologyRoute = routeIntToString(technology);
-        callService(() ->
-                sService.overrideRoutingTable(
-                        mContext.getUser().getIdentifier(),
-                        protocolRoute,
-                        technologyRoute,
-                        mContext.getPackageName()));
-    }
-
-    /**
-     * Restore the NFC controller routing table,
-     * which was changed by {@link #overrideRoutingTable(Activity, int, int)}
-     *
-     * @param activity The Activity that requested NFC controller routing table to be changed.
-     * @throws IllegalArgumentException if the caller is not in the foreground.
-     *
-     * @hide
-     */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
-    public void recoverRoutingTable(@NonNull Activity activity) {
-        if (!activity.isResumed()) {
-            throw new IllegalArgumentException("Activity must be resumed.");
-        }
-        callService(() ->
-                sService.recoverRoutingTable(
-                    mContext.getUser().getIdentifier()));
-    }
-
-    /**
-     * Is EUICC supported as a Secure Element EE which supports off host card emulation.
-     *
-     * @return true if the device supports EUICC for off host card emulation, false otherwise.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public boolean isEuiccSupported() {
-        return callServiceReturn(() -> sService.isEuiccSupported(), false);
-    }
-
-    /**
-     * Setting the default subscription ID succeeded.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0;
-
-    /**
-     * Setting the default subscription ID failed because the subscription ID is invalid.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1;
-
-    /**
-     * Setting the default subscription ID failed because there was an internal error processing
-     * the request. For ex: NFC service died in the middle of handling the API.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2;
-
-    /**
-     * Setting the default subscription ID failed because this feature is not supported on the
-     * device.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3;
-
-    /**
-     * Setting the default subscription ID failed because of unknown error.
-     * @hide
-     */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public static final int SET_SUBSCRIPTION_ID_STATUS_UNKNOWN = -1;
-
-    /** @hide */
-    @IntDef(prefix = "SET_SUBSCRIPTION_ID_STATUS_",
-            value = {
-                    SET_SUBSCRIPTION_ID_STATUS_SUCCESS,
-                    SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID,
-                    SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR,
-                    SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED,
-                    SET_SUBSCRIPTION_ID_STATUS_UNKNOWN
-            })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SetSubscriptionIdStatus {}
-
-    /**
-     * Sets the system's default NFC subscription id.
-     *
-     * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this sets the
-     * default UICC NFCEE that will handle NFC offhost CE transactions </p>
-     *
-     * @param subscriptionId the default NFC subscription Id to set. User can get subscription id
-     *                       from {@link SubscriptionManager#getSubscriptionId(int)}
-     * @return status of the operation.
-     *
-     * @throws UnsupportedOperationException If the device does not have
-     * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
-     * @hide
-     */
-    @SystemApi
-    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
-    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public @SetSubscriptionIdStatus int setDefaultNfcSubscriptionId(int subscriptionId) {
-        return callServiceReturn(() ->
-                        sService.setDefaultNfcSubscriptionId(
-                                subscriptionId, mContext.getPackageName()),
-                SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR);
-    }
-
-    /**
-     * Returns the system's default NFC subscription id.
-     *
-     * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this returns the
-     * default UICC NFCEE that will handle NFC offhost CE transactions </p>
-     * <p> If the device has no UICC that can serve as NFCEE, this will return
-     * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.</p>
-     *
-     * @return the default NFC subscription Id if set,
-     * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} otherwise.
-     *
-     * @throws UnsupportedOperationException If the device does not have
-     * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
-     */
-    @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
-    @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
-    public int getDefaultNfcSubscriptionId() {
-        return callServiceReturn(() ->
-                sService.getDefaultNfcSubscriptionId(mContext.getPackageName()),
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-    }
-
-    /**
-     * Returns the value of {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT}.
-     *
-     * @param context A context
-     * @return A ComponentName for the setting value, or null.
-     *
-     * @hide
-     */
-    @SystemApi
-    @UserHandleAware
-    @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
-    @SuppressWarnings("AndroidFrameworkClientSidePermissionCheck")
-    @FlaggedApi(android.permission.flags.Flags.FLAG_WALLET_ROLE_ENABLED)
-    @Nullable
-    public static ComponentName getPreferredPaymentService(@NonNull Context context) {
-        context.checkCallingOrSelfPermission(Manifest.permission.NFC_PREFERRED_PAYMENT_INFO);
-        String defaultPaymentComponent = Settings.Secure.getString(context.getContentResolver(),
-                Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT);
-
-        if (defaultPaymentComponent == null) {
-            return null;
-        }
-
-        return ComponentName.unflattenFromString(defaultPaymentComponent);
-    }
-
-    /** @hide */
-    interface ServiceCall {
-        void call() throws RemoteException;
-    }
-    /** @hide */
-    public static void callService(ServiceCall call) {
-        try {
-            if (sService == null) {
-                NfcAdapter.attemptDeadServiceRecovery(
-                    new RemoteException("NFC CardEmulation Service is null"));
-                sService = NfcAdapter.getCardEmulationService();
-            }
-            call.call();
-        } catch (RemoteException e) {
-            NfcAdapter.attemptDeadServiceRecovery(e);
-            sService = NfcAdapter.getCardEmulationService();
-            try {
-                call.call();
-            } catch (RemoteException ee) {
-                ee.rethrowAsRuntimeException();
-            }
-        }
-    }
-    /** @hide */
-    interface ServiceCallReturn<T> {
-        T call() throws RemoteException;
-    }
-    /** @hide */
-    public static <T> T callServiceReturn(ServiceCallReturn<T> call, T defaultReturn) {
-        try {
-            if (sService == null) {
-                NfcAdapter.attemptDeadServiceRecovery(
-                    new RemoteException("NFC CardEmulation Service is null"));
-                sService = NfcAdapter.getCardEmulationService();
-            }
-            return call.call();
-        } catch (RemoteException e) {
-            NfcAdapter.attemptDeadServiceRecovery(e);
-            sService = NfcAdapter.getCardEmulationService();
-            // Try one more time
-            try {
-                return call.call();
-            } catch (RemoteException ee) {
-                ee.rethrowAsRuntimeException();
-            }
-        }
-        return defaultReturn;
-    }
-
-    /** @hide */
-    public static String routeIntToString(@ProtocolAndTechnologyRoute int route) {
-        return switch (route) {
-            case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH";
-            case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "eSE";
-            case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "SIM";
-            case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null;
-            case PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT -> "default";
-            default -> throw new IllegalStateException("Unexpected value: " + route);
-        };
-    }
-
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0;
-
-    /**
-     * This error is reported when the NFC command watchdog restarts the NFC stack.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1;
-
-    /**
-     * This error is reported when the NFC controller does not respond or there's an NCI transport
-     * error.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2;
-
-    /**
-     * This error is reported when the NFC stack times out while waiting for a response to a command
-     * sent to the NFC hardware.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public static final int NFC_INTERNAL_ERROR_COMMAND_TIMEOUT = 3;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    @IntDef(prefix = "NFC_INTERNAL_ERROR_", value = {
-            NFC_INTERNAL_ERROR_UNKNOWN,
-            NFC_INTERNAL_ERROR_NFC_CRASH_RESTART,
-            NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR,
-            NFC_INTERNAL_ERROR_COMMAND_TIMEOUT,
-    })
-    public @interface NfcInternalErrorType {}
-
-    /** Listener for preferred service state changes. */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public interface NfcEventCallback {
-        /**
-         * This method is called when this package gains or loses preferred Nfc service status,
-         * either the Default Wallet Role holder (see {@link
-         * android.app.role.RoleManager#ROLE_WALLET}) or the preferred service of the foreground
-         * activity set with {@link #setPreferredService(Activity, ComponentName)}
-         *
-         * @param isPreferred true is this service has become the preferred Nfc service, false if it
-         *     is no longer the preferred service
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onPreferredServiceChanged(boolean isPreferred) {}
-
-        /**
-         * This method is called when observe mode has been enabled or disabled.
-         *
-         * @param isEnabled true if observe mode has been enabled, false if it has been disabled
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onObserveModeStateChanged(boolean isEnabled) {}
-
-        /**
-         * This method is called when an AID conflict is detected during an NFC transaction. This
-         * can happen when multiple services are registered for the same AID. If your service is
-         * registered for this AID you may want to instruct users to bring your app to the
-         * foreground and ensure you call {@link #setPreferredService(Activity, ComponentName)}
-         * to ensure the transaction is routed to your service.
-         *
-         * @param aid The AID that is in conflict
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onAidConflictOccurred(@NonNull String aid) {}
-
-        /**
-         * This method is called when an AID is not routed to any service during an NFC
-         * transaction. This can happen when no service is registered for the given AID.
-         *
-         * @param aid the AID that was not routed
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onAidNotRouted(@NonNull String aid) {}
-
-        /**
-         * This method is called when the NFC state changes.
-         *
-         * @see NfcAdapter#getAdapterState()
-         *
-         * @param state The new NFC state
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onNfcStateChanged(@NfcAdapter.AdapterState int state) {}
-        /**
-         * This method is called when the NFC controller is in card emulation mode and an NFC
-         * reader's field is either detected or lost.
-         *
-         * @param isDetected true if an NFC reader is detected, false if it is lost
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onRemoteFieldChanged(boolean isDetected) {}
-
-        /**
-         * This method is called when an internal error is reported by the NFC stack.
-         *
-         * No action is required in response to these events as the NFC stack will automatically
-         * attempt to recover. These errors are reported for informational purposes only.
-         *
-         * Note that these errors can be reported when performing various internal NFC operations
-         * (such as during device shutdown) and cannot always be explicitly correlated with NFC
-         * transaction failures.
-         *
-         * @param errorType The type of the internal error
-         */
-        @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-        default void onInternalErrorReported(@NfcInternalErrorType int errorType) {}
-    }
-
-    private final ArrayMap<NfcEventCallback, Executor> mNfcEventCallbacks = new ArrayMap<>();
-
-    final INfcEventCallback mINfcEventCallback =
-            new INfcEventCallback.Stub() {
-                public void onPreferredServiceChanged(ComponentNameAndUser componentNameAndUser) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    boolean isPreferred =
-                            componentNameAndUser != null
-                                    && componentNameAndUser.getUserId()
-                                            == mContext.getUser().getIdentifier()
-                                    && componentNameAndUser.getComponentName() != null
-                                    && Objects.equals(
-                                            mContext.getPackageName(),
-                                            componentNameAndUser.getComponentName()
-                                                    .getPackageName());
-                    callListeners(listener -> listener.onPreferredServiceChanged(isPreferred));
-                }
-
-                public void onObserveModeStateChanged(boolean isEnabled) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onObserveModeStateChanged(isEnabled));
-                }
-
-                public void onAidConflictOccurred(String aid) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onAidConflictOccurred(aid));
-                }
-
-                public void onAidNotRouted(String aid) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onAidNotRouted(aid));
-                }
-
-                public void onNfcStateChanged(int state) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onNfcStateChanged(state));
-                }
-
-                public void onRemoteFieldChanged(boolean isDetected) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onRemoteFieldChanged(isDetected));
-                }
-
-                public void onInternalErrorReported(@NfcInternalErrorType int errorType) {
-                    if (!android.nfc.Flags.nfcEventListener()) {
-                        return;
-                    }
-                    callListeners(listener -> listener.onInternalErrorReported(errorType));
-                }
-
-                interface ListenerCall {
-                    void invoke(NfcEventCallback listener);
-                }
-
-                private void callListeners(ListenerCall listenerCall) {
-                    synchronized (mNfcEventCallbacks) {
-                        mNfcEventCallbacks.forEach(
-                            (listener, executor) -> {
-                                executor.execute(() -> listenerCall.invoke(listener));
-                            });
-                    }
-                }
-            };
-
-    /**
-     * Register a listener for NFC Events.
-     *
-     * @param executor The Executor to run the call back with
-     * @param listener The listener to register
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public void registerNfcEventCallback(
-            @NonNull @CallbackExecutor Executor executor, @NonNull NfcEventCallback listener) {
-        if (!android.nfc.Flags.nfcEventListener()) {
-            return;
-        }
-        synchronized (mNfcEventCallbacks) {
-            mNfcEventCallbacks.put(listener, executor);
-            if (mNfcEventCallbacks.size() == 1) {
-                callService(() -> sService.registerNfcEventCallback(mINfcEventCallback));
-            }
-        }
-    }
-
-    /**
-     * Unregister a preferred service listener that was previously registered with {@link
-     * #registerNfcEventCallback(Executor, NfcEventCallback)}
-     *
-     * @param listener The previously registered listener to unregister
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
-    public void unregisterNfcEventCallback(@NonNull NfcEventCallback listener) {
-        if (!android.nfc.Flags.nfcEventListener()) {
-            return;
-        }
-        synchronized (mNfcEventCallbacks) {
-            mNfcEventCallbacks.remove(listener);
-            if (mNfcEventCallbacks.size() == 0) {
-                callService(() -> sService.unregisterNfcEventCallback(mINfcEventCallback));
-            }
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
deleted file mode 100644
index fbf2203..0000000
--- a/nfc/java/android/nfc/cardemulation/HostApduService.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.SuppressLint;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.nfc.NfcAdapter;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * <p>HostApduService is a convenience {@link Service} class that can be
- * extended to emulate an NFC card inside an Android
- * service component.
- *
- * <div class="special reference">
- * <h3>Developer Guide</h3>
- * For a general introduction to card emulation, see
- * <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html">
- * Host-based Card Emulation</a>.</p>
- * </div>
- *
- * <h3>NFC Protocols</h3>
- * <p>Cards emulated by this class are based on the NFC-Forum ISO-DEP
- * protocol (based on ISO/IEC 14443-4) and support processing
- * command Application Protocol Data Units (APDUs) as
- * defined in the ISO/IEC 7816-4 specification.
- *
- * <h3>Service selection</h3>
- * <p>When a remote NFC device wants to talk to your
- * service, it sends a so-called
- * "SELECT AID" APDU as defined in the ISO/IEC 7816-4 specification.
- * The AID is an application identifier defined in ISO/IEC 7816-4.
- *
- * <p>The registration procedure for AIDs is defined in the
- * ISO/IEC 7816-5 specification. If you don't want to register an
- * AID, you are free to use AIDs in the proprietary range:
- * bits 8-5 of the first byte must each be set to '1'. For example,
- * "0xF00102030405" is a proprietary AID. If you do use proprietary
- * AIDs, it is recommended to choose an AID of at least 6 bytes,
- * to reduce the risk of collisions with other applications that
- * might be using proprietary AIDs as well.
- *
- * <h3>AID groups</h3>
- * <p>In some cases, a service may need to register multiple AIDs
- * to implement a certain application, and it needs to be sure
- * that it is the default handler for all of these AIDs (as opposed
- * to some AIDs in the group going to another service).
- *
- * <p>An AID group is a list of AIDs that should be considered as
- * belonging together by the OS. For all AIDs in an AID group, the
- * OS will guarantee one of the following:
- * <ul>
- * <li>All AIDs in the group are routed to this service
- * <li>No AIDs in the group are routed to this service
- * </ul>
- * In other words, there is no in-between state, where some AIDs
- * in the group can be routed to this service, and some to another.
- * <h3>AID groups and categories</h3>
- * <p>Each AID group can be associated with a category. This allows
- * the Android OS to classify services, and it allows the user to
- * set defaults at the category level instead of the AID level.
- *
- * <p>You can use
- * {@link CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String)}
- * to determine if your service is the default handler for a category.
- *
- * <p>In this version of the platform, the only known categories
- * are {@link CardEmulation#CATEGORY_PAYMENT} and {@link CardEmulation#CATEGORY_OTHER}.
- * AID groups without a category, or with a category that is not recognized
- * by the current platform version, will automatically be
- * grouped into the {@link CardEmulation#CATEGORY_OTHER} category.
- * <h3>Service AID registration</h3>
- * <p>To tell the platform which AIDs groups
- * are requested by this service, a {@link #SERVICE_META_DATA}
- * entry must be included in the declaration of the service. An
- * example of a HostApduService manifest declaration is shown below:
- * <pre> &lt;service android:name=".MyHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"&gt;
- *     &lt;intent-filter&gt;
- *         &lt;action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/&gt;
- *     &lt;/intent-filter&gt;
- *     &lt;meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/apduservice"/&gt;
- * &lt;/service&gt;</pre>
- *
- * This meta-data tag points to an apduservice.xml file.
- * An example of this file with a single AID group declaration is shown below:
- * <pre>
- * &lt;host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
- *           android:description="@string/servicedesc" android:requireDeviceUnlock="false"&gt;
- *       &lt;aid-group android:description="@string/aiddescription" android:category="other">
- *           &lt;aid-filter android:name="F0010203040506"/&gt;
- *           &lt;aid-filter android:name="F0394148148100"/&gt;
- *       &lt;/aid-group&gt;
- * &lt;/host-apdu-service&gt;
- * </pre>
- *
- * <p>The {@link android.R.styleable#HostApduService &lt;host-apdu-service&gt;} is required
- * to contain a
- * {@link android.R.styleable#HostApduService_description &lt;android:description&gt;}
- * attribute that contains a user-friendly description of the service that may be shown in UI.
- * The
- * {@link android.R.styleable#HostApduService_requireDeviceUnlock &lt;requireDeviceUnlock&gt;}
- * attribute can be used to specify that the device must be unlocked before this service
- * can be invoked to handle APDUs.
- * <p>The {@link android.R.styleable#HostApduService &lt;host-apdu-service&gt;} must
- * contain one or more {@link android.R.styleable#AidGroup &lt;aid-group&gt;} tags.
- * Each {@link android.R.styleable#AidGroup &lt;aid-group&gt;} must contain one or
- * more {@link android.R.styleable#AidFilter &lt;aid-filter&gt;} tags, each of which
- * contains a single AID. The AID must be specified in hexadecimal format, and contain
- * an even number of characters.
- * <h3>AID conflict resolution</h3>
- * Multiple HostApduServices may be installed on a single device, and the same AID
- * can be registered by more than one service. The Android platform resolves AID
- * conflicts depending on which category an AID belongs to. Each category may
- * have a different conflict resolution policy. For example, for some categories
- * the user may be able to select a default service in the Android settings UI.
- * For other categories, to policy may be to always ask the user which service
- * is to be invoked in case of conflict.
- *
- * To query the conflict resolution policy for a certain category, see
- * {@link CardEmulation#getSelectionModeForCategory(String)}.
- *
- * <h3>Data exchange</h3>
- * <p>Once the platform has resolved a "SELECT AID" command APDU to a specific
- * service component, the "SELECT AID" command APDU and all subsequent
- * command APDUs will be sent to that service through
- * {@link #processCommandApdu(byte[], Bundle)}, until either:
- * <ul>
- * <li>The NFC link is broken</li>
- * <li>A "SELECT AID" APDU is received which resolves to another service</li>
- * </ul>
- * These two scenarios are indicated by a call to {@link #onDeactivated(int)}.
- *
- * <p class="note">Use of this class requires the
- * {@link PackageManager#FEATURE_NFC_HOST_CARD_EMULATION} to be present
- * on the device.
- *
- */
-public abstract class HostApduService extends Service {
-    /**
-     * The {@link Intent} action that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE =
-            "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
-
-    /**
-     * The name of the meta-data element that contains
-     * more information about this service.
-     */
-    public static final String SERVICE_META_DATA =
-            "android.nfc.cardemulation.host_apdu_service";
-
-    /**
-     * Reason for {@link #onDeactivated(int)}.
-     * Indicates deactivation was due to the NFC link
-     * being lost.
-     */
-    public static final int DEACTIVATION_LINK_LOSS = 0;
-
-    /**
-     * Reason for {@link #onDeactivated(int)}.
-     *
-     * <p>Indicates deactivation was due to a different AID
-     * being selected (which implicitly deselects the AID
-     * currently active on the logical channel).
-     *
-     * <p>Note that this next AID may still be resolved to this
-     * service, in which case {@link #processCommandApdu(byte[], Bundle)}
-     * will be called again.
-     */
-    public static final int DEACTIVATION_DESELECTED = 1;
-
-    static final String TAG = "ApduService";
-
-    /**
-     * MSG_COMMAND_APDU is sent by NfcService when
-     * a 7816-4 command APDU has been received.
-     *
-     * @hide
-     */
-    public static final int MSG_COMMAND_APDU = 0;
-
-    /**
-     * MSG_RESPONSE_APDU is sent to NfcService to send
-     * a response APDU back to the remote device.
-     *
-     * @hide
-     */
-    public static final int MSG_RESPONSE_APDU = 1;
-
-    /**
-     * MSG_DEACTIVATED is sent by NfcService when
-     * the current session is finished; either because
-     * another AID was selected that resolved to
-     * another service, or because the NFC link
-     * was deactivated.
-     *
-     * @hide
-     */
-    public static final int MSG_DEACTIVATED = 2;
-
-    /**
-     *
-     * @hide
-     */
-    public static final int MSG_UNHANDLED = 3;
-
-    /**
-     * @hide
-     */
-    public static final int MSG_POLLING_LOOP = 4;
-
-
-    /**
-     * @hide
-     */
-    public static final String KEY_DATA = "data";
-
-    /**
-     * @hide
-     */
-    public static final String KEY_POLLING_LOOP_FRAMES_BUNDLE =
-            "android.nfc.cardemulation.POLLING_FRAMES";
-
-    /**
-     * Messenger interface to NfcService for sending responses.
-     * Only accessed on main thread by the message handler.
-     *
-     * @hide
-     */
-    Messenger mNfcService = null;
-
-    final Messenger mMessenger = new Messenger(new MsgHandler());
-
-    final class MsgHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MSG_COMMAND_APDU:
-                Bundle dataBundle = msg.getData();
-                if (dataBundle == null) {
-                    return;
-                }
-                if (mNfcService == null) mNfcService = msg.replyTo;
-
-                byte[] apdu = dataBundle.getByteArray(KEY_DATA);
-                if (apdu != null) {
-                        HostApduService has = HostApduService.this;
-                    byte[] responseApdu = processCommandApdu(apdu, null);
-                    if (responseApdu != null) {
-                        if (mNfcService == null) {
-                            Log.e(TAG, "Response not sent; service was deactivated.");
-                            return;
-                        }
-                        Message responseMsg = Message.obtain(null, MSG_RESPONSE_APDU);
-                        Bundle responseBundle = new Bundle();
-                        responseBundle.putByteArray(KEY_DATA, responseApdu);
-                        responseMsg.setData(responseBundle);
-                        responseMsg.replyTo = mMessenger;
-                        try {
-                            mNfcService.send(responseMsg);
-                        } catch (RemoteException e) {
-                            Log.e(TAG, "Response not sent; RemoteException calling into " +
-                                    "NfcService.");
-                        }
-                    }
-                } else {
-                    Log.e(TAG, "Received MSG_COMMAND_APDU without data.");
-                }
-                break;
-            case MSG_RESPONSE_APDU:
-                if (mNfcService == null) {
-                    Log.e(TAG, "Response not sent; service was deactivated.");
-                    return;
-                }
-                try {
-                    msg.replyTo = mMessenger;
-                    mNfcService.send(msg);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException calling into NfcService.");
-                }
-                break;
-            case MSG_DEACTIVATED:
-                // Make sure we won't call into NfcService again
-                mNfcService = null;
-                onDeactivated(msg.arg1);
-                break;
-            case MSG_UNHANDLED:
-                if (mNfcService == null) {
-                    Log.e(TAG, "notifyUnhandled not sent; service was deactivated.");
-                    return;
-                }
-                try {
-                    msg.replyTo = mMessenger;
-                    mNfcService.send(msg);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException calling into NfcService.");
-                }
-                break;
-                case MSG_POLLING_LOOP:
-                    if (android.nfc.Flags.nfcReadPollingLoop()) {
-                        ArrayList<PollingFrame> pollingFrames =
-                                msg.getData().getParcelableArrayList(
-                                    KEY_POLLING_LOOP_FRAMES_BUNDLE, PollingFrame.class);
-                        processPollingFrames(pollingFrames);
-                    }
-                    break;
-                default:
-                super.handleMessage(msg);
-            }
-        }
-    }
-
-    @Override
-    public final IBinder onBind(Intent intent) {
-        return mMessenger.getBinder();
-    }
-
-    /**
-     * Sends a response APDU back to the remote device.
-     *
-     * <p>Note: this method may be called from any thread and will not block.
-     * @param responseApdu A byte-array containing the reponse APDU.
-     */
-    public final void sendResponseApdu(byte[] responseApdu) {
-        Message responseMsg = Message.obtain(null, MSG_RESPONSE_APDU);
-        Bundle dataBundle = new Bundle();
-        dataBundle.putByteArray(KEY_DATA, responseApdu);
-        responseMsg.setData(dataBundle);
-        try {
-            mMessenger.send(responseMsg);
-        } catch (RemoteException e) {
-            Log.e("TAG", "Local messenger has died.");
-        }
-    }
-
-    /**
-     * Calling this method allows the service to tell the OS
-     * that it won't be able to complete this transaction -
-     * for example, because it requires data connectivity
-     * that is not present at that moment.
-     *
-     * The OS may use this indication to give the user a list
-     * of alternative applications that can handle the last
-     * AID that was selected. If the user would select an
-     * application from the list, that action by itself
-     * will not cause the default to be changed; the selected
-     * application will be invoked for the next tap only.
-     *
-     * If there are no other applications that can handle
-     * this transaction, the OS will show an error dialog
-     * indicating your service could not complete the
-     * transaction.
-     *
-     * <p>Note: this method may be called anywhere between
-     *    the first {@link #processCommandApdu(byte[], Bundle)}
-     *    call and a {@link #onDeactivated(int)} call.
-     */
-    public final void notifyUnhandled() {
-        Message unhandledMsg = Message.obtain(null, MSG_UNHANDLED);
-        try {
-            mMessenger.send(unhandledMsg);
-        } catch (RemoteException e) {
-            Log.e("TAG", "Local messenger has died.");
-        }
-    }
-
-    /**
-     * This method is called when polling frames have been received from a
-     * remote device. If the device is in observe mode, the service should
-     * call {@link NfcAdapter#allowTransaction()} once it is ready to proceed
-     * with the transaction. If the device is not in observe mode, the service
-     * can use this polling frame information to determine how to proceed if it
-     * subsequently has {@link #processCommandApdu(byte[], Bundle)} called. The
-     * service must override this method inorder to receive polling frames,
-     * otherwise the base implementation drops the frame.
-     *
-     * @param frame A description of the polling frame.
-     */
-    @SuppressLint("OnNameExpected")
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public void processPollingFrames(@NonNull List<PollingFrame> frame) {
-    }
-
-    /**
-     * <p>This method will be called when a command APDU has been received
-     * from a remote device. A response APDU can be provided directly
-     * by returning a byte-array in this method. Note that in general
-     * response APDUs must be sent as quickly as possible, given the fact
-     * that the user is likely holding their device over an NFC reader
-     * when this method is called.
-     *
-     * <p class="note">If there are multiple services that have registered for the same
-     * AIDs in their meta-data entry, you will only get called if the user has
-     * explicitly selected your service, either as a default or just for the next tap.
-     *
-     * <p class="note">This method is running on the main thread of your application.
-     * If you cannot return a response APDU immediately, return null
-     * and use the {@link #sendResponseApdu(byte[])} method later.
-     *
-     * @param commandApdu The APDU that was received from the remote device
-     * @param extras A bundle containing extra data. May be null.
-     * @return a byte-array containing the response APDU, or null if no
-     *         response APDU can be sent at this point.
-     */
-    public abstract byte[] processCommandApdu(byte[] commandApdu, Bundle extras);
-
-    /**
-     * This method will be called in two possible scenarios:
-     * <li>The NFC link has been deactivated or lost
-     * <li>A different AID has been selected and was resolved to a different
-     *     service component
-     * @param reason Either {@link #DEACTIVATION_LINK_LOSS} or {@link #DEACTIVATION_DESELECTED}
-     */
-    public abstract void onDeactivated(int reason);
-
-}
diff --git a/nfc/java/android/nfc/cardemulation/HostNfcFService.java b/nfc/java/android/nfc/cardemulation/HostNfcFService.java
deleted file mode 100644
index 65b5ca7..0000000
--- a/nfc/java/android/nfc/cardemulation/HostNfcFService.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * <p>HostNfcFService is a convenience {@link Service} class that can be
- * extended to emulate an NFC-F card inside an Android service component.
- *
- * <h3>NFC Protocols</h3>
- * <p>Cards emulated by this class are based on the NFC-Forum NFC-F
- * protocol (based on the JIS-X 6319-4 specification.)</p>
- *
- * <h3>System Code and NFCID2 registration</h3>
- * <p>A {@link HostNfcFService HostNfcFService service} can register
- * exactly one System Code and one NFCID2. For details about the use of
- * System Code and NFCID2, see the NFC Forum Digital specification.</p>
- * <p>To statically register a System Code and NFCID2 with the service, a {@link #SERVICE_META_DATA}
- * entry must be included in the declaration of the service.
- *
- * <p>All {@link HostNfcFService HostNfcFService} declarations in the manifest must require the
- * {@link android.Manifest.permission#BIND_NFC_SERVICE} permission
- * in their &lt;service&gt; tag, to ensure that only the platform can bind to your service.</p>
- *
- * <p>An example of a HostNfcFService manifest declaration is shown below:
- *
- * <pre> &lt;service android:name=".MyHostNfcFService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"&gt;
- *     &lt;intent-filter&gt;
- *         &lt;action android:name="android.nfc.cardemulation.action.HOST_NFCF_SERVICE"/&gt;
- *     &lt;/intent-filter&gt;
- *     &lt;meta-data android:name="android.nfc.cardemulation.host_nfcf_service" android:resource="@xml/nfcfservice"/&gt;
- * &lt;/service&gt;</pre>
- *
- * This meta-data tag points to an nfcfservice.xml file.
- * An example of this file with a System Code and NFCID2 declaration is shown below:
- * <pre>
- * &lt;host-nfcf-service xmlns:android="http://schemas.android.com/apk/res/android"
- *           android:description="@string/servicedesc"&gt;
- *       &lt;system-code-filter android:name="4000"/&gt;
- *       &lt;nfcid2-filter android:name="02FE000000000000"/&gt;
-         &lt;t3tPmm-filter android:name="FFFFFFFFFFFFFFFF"/&gt;
- * &lt;/host-nfcf-service&gt;
- * </pre>
- *
- * <p>The {@link android.R.styleable#HostNfcFService &lt;host-nfcf-service&gt;} is required
- * to contain a
- * {@link android.R.styleable#HostApduService_description &lt;android:description&gt;}
- * attribute that contains a user-friendly description of the service that may be shown in UI.
- * <p>The {@link android.R.styleable#HostNfcFService &lt;host-nfcf-service&gt;} must
- * contain:
- * <ul>
- * <li>Exactly one {@link android.R.styleable#SystemCodeFilter &lt;system-code-filter&gt;} tag.</li>
- * <li>Exactly one {@link android.R.styleable#Nfcid2Filter &lt;nfcid2-filter&gt;} tag.</li>
- * <li>Zero or one {@link android.R.styleable#T3tPmmFilter &lt;t3tPmm-filter&gt;} tag.</li>
- * </ul>
- * </p>
- *
- * <p>Alternatively, the System Code and NFCID2 can be dynamically registererd for a service
- * by using the {@link NfcFCardEmulation#registerSystemCodeForService(ComponentName, String)} and
- * {@link NfcFCardEmulation#setNfcid2ForService(ComponentName, String)} methods.
- * </p>
- *
- * <h3>Service selection</h3>
- * <p>When a remote NFC devices wants to communicate with your service, it
- * sends a SENSF_REQ command to the NFC controller, requesting a System Code.
- * If a {@link NfcFCardEmulation NfcFCardEmulation service} has registered
- * this system code and has been enabled by the foreground application, the
- * NFC controller will respond with the NFCID2 that is registered for this service.
- * The reader can then continue data exchange with this service by using the NFCID2.</p>
- *
- * <h3>Data exchange</h3>
- * <p>After service selection, all frames addressed to the NFCID2 of this service will
- * be sent through {@link #processNfcFPacket(byte[], Bundle)}, until the NFC link is
- * broken.<p>
- *
- * <p>When the NFC link is broken, {@link #onDeactivated(int)} will be called.</p>
- */
-public abstract class HostNfcFService extends Service {
-    /**
-     * The {@link Intent} action that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE =
-            "android.nfc.cardemulation.action.HOST_NFCF_SERVICE";
-
-    /**
-     * The name of the meta-data element that contains
-     * more information about this service.
-     */
-    public static final String SERVICE_META_DATA =
-            "android.nfc.cardemulation.host_nfcf_service";
-
-    /**
-     * Reason for {@link #onDeactivated(int)}.
-     * Indicates deactivation was due to the NFC link
-     * being lost.
-     */
-    public static final int DEACTIVATION_LINK_LOSS = 0;
-
-    static final String TAG = "NfcFService";
-
-    /**
-     * MSG_COMMAND_PACKET is sent by NfcService when
-     * a NFC-F command packet has been received.
-     *
-     * @hide
-     */
-    public static final int MSG_COMMAND_PACKET = 0;
-
-    /**
-     * MSG_RESPONSE_PACKET is sent to NfcService to send
-     * a response packet back to the remote device.
-     *
-     * @hide
-     */
-    public static final int MSG_RESPONSE_PACKET = 1;
-
-    /**
-     * MSG_DEACTIVATED is sent by NfcService when
-     * the current session is finished; because
-     * the NFC link was deactivated.
-     *
-     * @hide
-     */
-    public static final int MSG_DEACTIVATED = 2;
-
-   /**
-     * @hide
-     */
-    public static final String KEY_DATA = "data";
-
-    /**
-     * @hide
-     */
-    public static final String KEY_MESSENGER = "messenger";
-
-    /**
-     * Messenger interface to NfcService for sending responses.
-     * Only accessed on main thread by the message handler.
-     *
-     * @hide
-     */
-    Messenger mNfcService = null;
-
-    final Messenger mMessenger = new Messenger(new MsgHandler());
-
-    final class MsgHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case MSG_COMMAND_PACKET:
-                Bundle dataBundle = msg.getData();
-                if (dataBundle == null) {
-                    return;
-                }
-                if (mNfcService == null) mNfcService = msg.replyTo;
-
-                byte[] packet = dataBundle.getByteArray(KEY_DATA);
-                if (packet != null) {
-                    byte[] responsePacket = processNfcFPacket(packet, null);
-                    if (responsePacket != null) {
-                        if (mNfcService == null) {
-                            Log.e(TAG, "Response not sent; service was deactivated.");
-                            return;
-                        }
-                        Message responseMsg = Message.obtain(null, MSG_RESPONSE_PACKET);
-                        Bundle responseBundle = new Bundle();
-                        responseBundle.putByteArray(KEY_DATA, responsePacket);
-                        responseMsg.setData(responseBundle);
-                        responseMsg.replyTo = mMessenger;
-                        try {
-                            mNfcService.send(responseMsg);
-                        } catch (RemoteException e) {
-                            Log.e("TAG", "Response not sent; RemoteException calling into " +
-                                    "NfcService.");
-                        }
-                    }
-                } else {
-                    Log.e(TAG, "Received MSG_COMMAND_PACKET without data.");
-                }
-                break;
-            case MSG_RESPONSE_PACKET:
-                if (mNfcService == null) {
-                    Log.e(TAG, "Response not sent; service was deactivated.");
-                    return;
-                }
-                try {
-                    msg.replyTo = mMessenger;
-                    mNfcService.send(msg);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException calling into NfcService.");
-                }
-                break;
-            case MSG_DEACTIVATED:
-                // Make sure we won't call into NfcService again
-                mNfcService = null;
-                onDeactivated(msg.arg1);
-                break;
-            default:
-                super.handleMessage(msg);
-            }
-        }
-    }
-
-    @Override
-    public final IBinder onBind(Intent intent) {
-        return mMessenger.getBinder();
-    }
-
-    /**
-     * Sends a response packet back to the remote device.
-     *
-     * <p>Note: this method may be called from any thread and will not block.
-     * @param responsePacket A byte-array containing the response packet.
-     */
-    public final void sendResponsePacket(byte[] responsePacket) {
-        Message responseMsg = Message.obtain(null, MSG_RESPONSE_PACKET);
-        Bundle dataBundle = new Bundle();
-        dataBundle.putByteArray(KEY_DATA, responsePacket);
-        responseMsg.setData(dataBundle);
-        try {
-            mMessenger.send(responseMsg);
-        } catch (RemoteException e) {
-            Log.e("TAG", "Local messenger has died.");
-        }
-    }
-
-    /**
-     * <p>This method will be called when a NFC-F packet has been received
-     * from a remote device. A response packet can be provided directly
-     * by returning a byte-array in this method. Note that in general
-     * response packets must be sent as quickly as possible, given the fact
-     * that the user is likely holding their device over an NFC reader
-     * when this method is called.
-     *
-     * <p class="note">This method is running on the main thread of your application.
-     * If you cannot return a response packet immediately, return null
-     * and use the {@link #sendResponsePacket(byte[])} method later.
-     *
-     * @param commandPacket The NFC-F packet that was received from the remote device
-     * @param extras A bundle containing extra data. May be null.
-     * @return a byte-array containing the response packet, or null if no
-     *         response packet can be sent at this point.
-     */
-    public abstract byte[] processNfcFPacket(byte[] commandPacket, Bundle extras);
-
-    /**
-     * This method will be called in following possible scenarios:
-     * <li>The NFC link has been lost
-     * @param reason {@link #DEACTIVATION_LINK_LOSS}
-     */
-    public abstract void onDeactivated(int reason);
-}
diff --git a/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java b/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java
deleted file mode 100644
index 48bbf5b6..0000000
--- a/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.nfc.INfcFCardEmulation;
-import android.nfc.NfcAdapter;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * This class can be used to query the state of
- * NFC-F card emulation services.
- *
- * For a general introduction into NFC card emulation,
- * please read the <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html">
- * NFC card emulation developer guide</a>.</p>
- *
- * <p class="note">Use of this class requires the
- * {@link PackageManager#FEATURE_NFC_HOST_CARD_EMULATION_NFCF}
- * to be present on the device.
- */
-public final class NfcFCardEmulation {
-    static final String TAG = "NfcFCardEmulation";
-
-    static boolean sIsInitialized = false;
-    static HashMap<Context, NfcFCardEmulation> sCardEmus = new HashMap<Context, NfcFCardEmulation>();
-    static INfcFCardEmulation sService;
-
-    final Context mContext;
-
-    private NfcFCardEmulation(Context context, INfcFCardEmulation service) {
-        mContext = context.getApplicationContext();
-        sService = service;
-    }
-
-    /**
-     * Helper to get an instance of this class.
-     *
-     * @param adapter A reference to an NfcAdapter object.
-     * @return
-     */
-    public static synchronized NfcFCardEmulation getInstance(NfcAdapter adapter) {
-        if (adapter == null) throw new NullPointerException("NfcAdapter is null");
-        Context context = adapter.getContext();
-        if (context == null) {
-            Log.e(TAG, "NfcAdapter context is null.");
-            throw new UnsupportedOperationException();
-        }
-        if (!sIsInitialized) {
-            PackageManager pm = context.getPackageManager();
-            if (pm == null) {
-                Log.e(TAG, "Cannot get PackageManager");
-                throw new UnsupportedOperationException();
-            }
-            if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)) {
-                Log.e(TAG, "This device does not support NFC-F card emulation");
-                throw new UnsupportedOperationException();
-            }
-            sIsInitialized = true;
-        }
-        NfcFCardEmulation manager = sCardEmus.get(context);
-        if (manager == null) {
-            // Get card emu service
-            INfcFCardEmulation service = adapter.getNfcFCardEmulationService();
-            if (service == null) {
-                Log.e(TAG, "This device does not implement the INfcFCardEmulation interface.");
-                throw new UnsupportedOperationException();
-            }
-            manager = new NfcFCardEmulation(context, service);
-            sCardEmus.put(context, manager);
-        }
-        return manager;
-    }
-
-    /**
-     * Retrieves the current System Code for the specified service.
-     *
-     * <p>Before calling {@link #registerSystemCodeForService(ComponentName, String)},
-     * the System Code contained in the Manifest file is returned. After calling
-     * {@link #registerSystemCodeForService(ComponentName, String)}, the System Code
-     * registered there is returned. After calling
-     * {@link #unregisterSystemCodeForService(ComponentName)}, "null" is returned.
-     *
-     * @param service The component name of the service
-     * @return the current System Code
-     */
-    public String getSystemCodeForService(ComponentName service) throws RuntimeException {
-        if (service == null) {
-            throw new NullPointerException("service is null");
-        }
-        try {
-            return sService.getSystemCodeForService(mContext.getUser().getIdentifier(), service);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return null;
-            }
-            try {
-                return sService.getSystemCodeForService(mContext.getUser().getIdentifier(),
-                        service);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Registers a System Code for the specified service.
-     *
-     * <p>The System Code must be in range from "4000" to "4FFF" (excluding "4*FF").
-     *
-     * <p>If a System Code was previously registered for this service
-     * (either statically through the manifest, or dynamically by using this API),
-     * it will be replaced with this one.
-     *
-     * <p>Even if the same System Code is already registered for another service,
-     * this method succeeds in registering the System Code.
-     *
-     * <p>Note that you can only register a System Code for a service that
-     * is running under the same UID as the caller of this API. Typically
-     * this means you need to call this from the same
-     * package as the service itself, though UIDs can also
-     * be shared between packages using shared UIDs.
-     *
-     * @param service The component name of the service
-     * @param systemCode The System Code to be registered
-     * @return whether the registration was successful.
-     */
-    public boolean registerSystemCodeForService(ComponentName service, String systemCode)
-            throws RuntimeException {
-        if (service == null || systemCode == null) {
-            throw new NullPointerException("service or systemCode is null");
-        }
-        try {
-            return sService.registerSystemCodeForService(mContext.getUser().getIdentifier(),
-                    service, systemCode);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return false;
-            }
-            try {
-                return sService.registerSystemCodeForService(mContext.getUser().getIdentifier(),
-                        service, systemCode);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Removes a registered System Code for the specified service.
-     *
-     * @param service The component name of the service
-     * @return whether the System Code was successfully removed.
-     */
-    public boolean unregisterSystemCodeForService(ComponentName service) throws RuntimeException {
-        if (service == null) {
-            throw new NullPointerException("service is null");
-        }
-        try {
-            return sService.removeSystemCodeForService(mContext.getUser().getIdentifier(), service);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return false;
-            }
-            try {
-                return sService.removeSystemCodeForService(mContext.getUser().getIdentifier(),
-                        service);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Retrieves the current NFCID2 for the specified service.
-     *
-     * <p>Before calling {@link #setNfcid2ForService(ComponentName, String)},
-     * the NFCID2 contained in the Manifest file is returned. If "random" is specified
-     * in the Manifest file, a random number assigned by the system at installation time
-     * is returned. After setting an NFCID2
-     * with {@link #setNfcid2ForService(ComponentName, String)}, this NFCID2 is returned.
-     *
-     * @param service The component name of the service
-     * @return the current NFCID2
-     */
-    public String getNfcid2ForService(ComponentName service) throws RuntimeException {
-        if (service == null) {
-            throw new NullPointerException("service is null");
-        }
-        try {
-            return sService.getNfcid2ForService(mContext.getUser().getIdentifier(), service);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return null;
-            }
-            try {
-                return sService.getNfcid2ForService(mContext.getUser().getIdentifier(), service);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Set a NFCID2 for the specified service.
-     *
-     * <p>The NFCID2 must be in range from "02FE000000000000" to "02FEFFFFFFFFFFFF".
-     *
-     * <p>If a NFCID2 was previously set for this service
-     * (either statically through the manifest, or dynamically by using this API),
-     * it will be replaced.
-     *
-     * <p>Note that you can only set the NFCID2 for a service that
-     * is running under the same UID as the caller of this API. Typically
-     * this means you need to call this from the same
-     * package as the service itself, though UIDs can also
-     * be shared between packages using shared UIDs.
-     *
-     * @param service The component name of the service
-     * @param nfcid2 The NFCID2 to be registered
-     * @return whether the setting was successful.
-     */
-    public boolean setNfcid2ForService(ComponentName service, String nfcid2)
-            throws RuntimeException {
-        if (service == null || nfcid2 == null) {
-            throw new NullPointerException("service or nfcid2 is null");
-        }
-        try {
-            return sService.setNfcid2ForService(mContext.getUser().getIdentifier(),
-                    service, nfcid2);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return false;
-            }
-            try {
-                return sService.setNfcid2ForService(mContext.getUser().getIdentifier(),
-                        service, nfcid2);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Allows a foreground application to specify which card emulation service
-     * should be enabled while a specific Activity is in the foreground.
-     *
-     * <p>The specified HCE-F service is only enabled when the corresponding application is
-     * in the foreground and this method has been called. When the application is moved to
-     * the background, {@link #disableService(Activity)} is called, or
-     * NFCID2 or System Code is replaced, the HCE-F service is disabled.
-     *
-     * <p>The specified Activity must currently be in resumed state. A good
-     * paradigm is to call this method in your {@link Activity#onResume}, and to call
-     * {@link #disableService(Activity)} in your {@link Activity#onPause}.
-     *
-     * <p>Note that this preference is not persisted by the OS, and hence must be
-     * called every time the Activity is resumed.
-     *
-     * @param activity The activity which prefers this service to be invoked
-     * @param service The service to be preferred while this activity is in the foreground
-     * @return whether the registration was successful
-     */
-    public boolean enableService(Activity activity, ComponentName service) throws RuntimeException {
-        if (activity == null || service == null) {
-            throw new NullPointerException("activity or service is null");
-        }
-        // Verify the activity is in the foreground before calling into NfcService
-        if (!activity.isResumed()) {
-            throw new IllegalArgumentException("Activity must be resumed.");
-        }
-        try {
-            return sService.enableNfcFForegroundService(service);
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return false;
-            }
-            try {
-                return sService.enableNfcFForegroundService(service);
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Disables the service for the specified Activity.
-     *
-     * <p>Note that the specified Activity must still be in resumed
-     * state at the time of this call. A good place to call this method
-     * is in your {@link Activity#onPause} implementation.
-     *
-     * @param activity The activity which the service was registered for
-     * @return true when successful
-     */
-    public boolean disableService(Activity activity) throws RuntimeException {
-        if (activity == null) {
-            throw new NullPointerException("activity is null");
-        }
-        if (!activity.isResumed()) {
-            throw new IllegalArgumentException("Activity must be resumed.");
-        }
-        try {
-            return sService.disableNfcFForegroundService();
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return false;
-            }
-            try {
-                return sService.disableNfcFForegroundService();
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                ee.rethrowAsRuntimeException();
-                return false;
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public List<NfcFServiceInfo> getNfcFServices() {
-        try {
-            return sService.getNfcFServices(mContext.getUser().getIdentifier());
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return null;
-            }
-            try {
-                return sService.getNfcFServices(mContext.getUser().getIdentifier());
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                return null;
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public int getMaxNumOfRegisterableSystemCodes() {
-        try {
-            return sService.getMaxNumOfRegisterableSystemCodes();
-        } catch (RemoteException e) {
-            // Try one more time
-            recoverService();
-            if (sService == null) {
-                Log.e(TAG, "Failed to recover CardEmulationService.");
-                return -1;
-            }
-            try {
-                return sService.getMaxNumOfRegisterableSystemCodes();
-            } catch (RemoteException ee) {
-                Log.e(TAG, "Failed to reach CardEmulationService.");
-                return -1;
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public 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;
-    }
-
-    /**
-     * @hide
-     */
-    public 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;
-    }
-
-    void recoverService() {
-        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
-        sService = adapter.getNfcFCardEmulationService();
-    }
-
-}
-
diff --git a/nfc/java/android/nfc/cardemulation/OffHostApduService.java b/nfc/java/android/nfc/cardemulation/OffHostApduService.java
deleted file mode 100644
index 8d8a172..0000000
--- a/nfc/java/android/nfc/cardemulation/OffHostApduService.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.IBinder;
-
-/**
- * <p>OffHostApduService is a convenience {@link Service} class that can be
- * extended to describe one or more NFC applications that are residing
- * off-host, for example on an embedded secure element or a UICC.
- *
- * <div class="special reference">
- * <h3>Developer Guide</h3>
- * For a general introduction into the topic of card emulation,
- * please read the <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html">
- * NFC card emulation developer guide.</a></p>
- * </div>
- *
- * <h3>NFC Protocols</h3>
- * <p>Off-host applications represented by this class are based on the NFC-Forum ISO-DEP
- * protocol (based on ISO/IEC 14443-4) and support processing
- * command Application Protocol Data Units (APDUs) as
- * defined in the ISO/IEC 7816-4 specification.
- *
- * <h3>Service selection</h3>
- * <p>When a remote NFC device wants to talk to your
- * off-host NFC application, it sends a so-called
- * "SELECT AID" APDU as defined in the ISO/IEC 7816-4 specification.
- * The AID is an application identifier defined in ISO/IEC 7816-4.
- *
- * <p>The registration procedure for AIDs is defined in the
- * ISO/IEC 7816-5 specification. If you don't want to register an
- * AID, you are free to use AIDs in the proprietary range:
- * bits 8-5 of the first byte must each be set to '1'. For example,
- * "0xF00102030405" is a proprietary AID. If you do use proprietary
- * AIDs, it is recommended to choose an AID of at least 6 bytes,
- * to reduce the risk of collisions with other applications that
- * might be using proprietary AIDs as well.
- *
- * <h3>AID groups</h3>
- * <p>In some cases, an off-host environment may need to register multiple AIDs
- * to implement a certain application, and it needs to be sure
- * that it is the default handler for all of these AIDs (as opposed
- * to some AIDs in the group going to another service).
- *
- * <p>An AID group is a list of AIDs that should be considered as
- * belonging together by the OS. For all AIDs in an AID group, the
- * OS will guarantee one of the following:
- * <ul>
- * <li>All AIDs in the group are routed to the off-host execution environment
- * <li>No AIDs in the group are routed to the off-host execution environment
- * </ul>
- * In other words, there is no in-between state, where some AIDs
- * in the group can be routed to this off-host execution environment,
- * and some to another or a host-based {@link HostApduService}.
- * <h3>AID groups and categories</h3>
- * <p>Each AID group can be associated with a category. This allows
- * the Android OS to classify services, and it allows the user to
- * set defaults at the category level instead of the AID level.
- *
- * <p>You can use
- * {@link CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String)}
- * to determine if your off-host service is the default handler for a category.
- *
- * <p>In this version of the platform, the only known categories
- * are {@link CardEmulation#CATEGORY_PAYMENT} and {@link CardEmulation#CATEGORY_OTHER}.
- * AID groups without a category, or with a category that is not recognized
- * by the current platform version, will automatically be
- * grouped into the {@link CardEmulation#CATEGORY_OTHER} category.
- *
- * <h3>Service AID registration</h3>
- * <p>To tell the platform which AIDs
- * reside off-host and are managed by this service, a {@link #SERVICE_META_DATA}
- * entry must be included in the declaration of the service. An
- * example of a OffHostApduService manifest declaration is shown below:
- * <pre> &lt;service android:name=".MyOffHostApduService" android:exported="true" android:permission="android.permission.BIND_NFC_SERVICE"&gt;
- *     &lt;intent-filter&gt;
- *         &lt;action android:name="android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE"/&gt;
- *     &lt;/intent-filter&gt;
- *     &lt;meta-data android:name="android.nfc.cardemulation.off_host_apdu_service" android:resource="@xml/apduservice"/&gt;
- * &lt;/service&gt;</pre>
- *
- * This meta-data tag points to an apduservice.xml file.
- * An example of this file with a single AID group declaration is shown below:
- * <pre>
- * &lt;offhost-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
- *           android:description="@string/servicedesc"&gt;
- *       &lt;aid-group android:description="@string/subscription" android:category="other">
- *           &lt;aid-filter android:name="F0010203040506"/&gt;
- *           &lt;aid-filter android:name="F0394148148100"/&gt;
- *       &lt;/aid-group&gt;
- * &lt;/offhost-apdu-service&gt;
- * </pre>
- *
- * <p>The {@link android.R.styleable#OffHostApduService &lt;offhost-apdu-service&gt;} is required
- * to contain a
- * {@link android.R.styleable#OffHostApduService_description &lt;android:description&gt;}
- * attribute that contains a user-friendly description of the service that may be shown in UI.
- *
- * <p>The {@link android.R.styleable#OffHostApduService &lt;offhost-apdu-service&gt;} must
- * contain one or more {@link android.R.styleable#AidGroup &lt;aid-group&gt;} tags.
- * Each {@link android.R.styleable#AidGroup &lt;aid-group&gt;} must contain one or
- * more {@link android.R.styleable#AidFilter &lt;aid-filter&gt;} tags, each of which
- * contains a single AID. The AID must be specified in hexadecimal format, and contain
- * an even number of characters.
- *
- * <p>This registration will allow the service to be included
- * as an option for being the default handler for categories.
- * The Android OS will take care of correctly
- * routing the AIDs to the off-host execution environment,
- * based on which service the user has selected to be the handler for a certain category.
- *
- * <p>The service may define additional actions outside of the
- * Android namespace that provide further interaction with
- * the off-host execution environment.
- *
- * <p class="note">Use of this class requires the
- * {@link PackageManager#FEATURE_NFC_HOST_CARD_EMULATION} to be present
- * on the device.
- */
-public abstract class OffHostApduService extends Service {
-    /**
-     * The {@link Intent} action that must be declared as handled by the service.
-     */
-    @SdkConstant(SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE =
-            "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE";
-
-    /**
-     * The name of the meta-data element that contains
-     * more information about this service.
-     */
-    public static final String SERVICE_META_DATA =
-            "android.nfc.cardemulation.off_host_apdu_service";
-
-    /**
-     * The Android platform itself will not bind to this service,
-     * but merely uses its declaration to keep track of what AIDs
-     * the service is interested in. This information is then used
-     * to present the user with a list of applications that can handle
-     * an AID, as well as correctly route those AIDs either to the host (in case
-     * the user preferred a {@link HostApduService}), or to an off-host
-     * execution environment (in case the user preferred a {@link OffHostApduService}.
-     *
-     * Implementers may define additional actions outside of the
-     * Android namespace that allow further interactions with
-     * the off-host execution environment. Such implementations
-     * would need to override this method.
-     */
-    public abstract IBinder onBind(Intent intent);
-}
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.aidl b/nfc/java/android/nfc/cardemulation/PollingFrame.aidl
deleted file mode 100644
index 8e09f8b..0000000
--- a/nfc/java/android/nfc/cardemulation/PollingFrame.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-parcelable PollingFrame;
\ No newline at end of file
diff --git a/nfc/java/android/nfc/cardemulation/PollingFrame.java b/nfc/java/android/nfc/cardemulation/PollingFrame.java
deleted file mode 100644
index 5dcc84c..0000000
--- a/nfc/java/android/nfc/cardemulation/PollingFrame.java
+++ /dev/null
@@ -1,283 +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.nfc.cardemulation;
-
-import android.annotation.FlaggedApi;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HexFormat;
-import java.util.List;
-
-/**
- * Polling Frames represent data about individual frames of an NFC polling loop. These frames will
- * be delivered to subclasses of {@link HostApduService} that have registered filters with
- * {@link CardEmulation#registerPollingLoopFilterForService(ComponentName, String, boolean)} that
- * match a given frame in a loop and will be delivered through calls to
- * {@link HostApduService#processPollingFrames(List)}.
- */
-@FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-public final class PollingFrame implements Parcelable {
-
-    /**
-     * @hide
-     */
-    @IntDef(prefix = { "POLLING_LOOP_TYPE_"},
-        value = {
-            POLLING_LOOP_TYPE_A,
-            POLLING_LOOP_TYPE_B,
-            POLLING_LOOP_TYPE_F,
-            POLLING_LOOP_TYPE_OFF,
-            POLLING_LOOP_TYPE_ON,
-            POLLING_LOOP_TYPE_UNKNOWN
-        })
-    @Retention(RetentionPolicy.SOURCE)
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public @interface PollingFrameType {}
-
-    /**
-     * POLLING_LOOP_TYPE_A is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop is for NFC-A.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_A = 'A';
-
-    /**
-     * POLLING_LOOP_TYPE_B is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop is for NFC-B.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_B = 'B';
-
-    /**
-     * POLLING_LOOP_TYPE_F is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop is for NFC-F.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_F = 'F';
-
-    /**
-     * POLLING_LOOP_TYPE_ON is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop turns on.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_ON = 'O';
-
-    /**
-     * POLLING_LOOP_TYPE_OFF is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop turns off.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_OFF = 'X';
-
-    /**
-     * POLLING_LOOP_TYPE_UNKNOWN is the value associated with the key
-     * POLLING_LOOP_TYPE  in the Bundle passed to {@link HostApduService#processPollingFrames(List)}
-     * when the polling loop frame isn't recognized.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    public static final int POLLING_LOOP_TYPE_UNKNOWN = 'U';
-
-    /**
-     * KEY_POLLING_LOOP_TYPE is the Bundle key for the type of
-     * polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    private static final String KEY_POLLING_LOOP_TYPE = "android.nfc.cardemulation.TYPE";
-
-    /**
-     * KEY_POLLING_LOOP_DATA is the Bundle key for the raw data of captured from
-     * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-     */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    private static final String KEY_POLLING_LOOP_DATA = "android.nfc.cardemulation.DATA";
-
-    /**
-     * KEY_POLLING_LOOP_GAIN is the Bundle key for the field strength of
-     * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-    */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    private static final String KEY_POLLING_LOOP_GAIN = "android.nfc.cardemulation.GAIN";
-
-    /**
-     * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for the timestamp of
-     * the polling loop frame in the Bundle included in MSG_POLLING_LOOP.
-    */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    private static final String KEY_POLLING_LOOP_TIMESTAMP = "android.nfc.cardemulation.TIMESTAMP";
-
-    /**
-     * KEY_POLLING_LOOP_TIMESTAMP is the Bundle key for whether this polling frame triggered
-     * autoTransact in the Bundle included in MSG_POLLING_LOOP.
-    */
-    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
-    private static final String KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT =
-            "android.nfc.cardemulation.TRIGGERED_AUTOTRANSACT";
-
-
-    @PollingFrameType
-    private final int mType;
-    private final byte[] mData;
-    private final int mGain;
-    private final long mTimestamp;
-    private boolean mTriggeredAutoTransact;
-
-    public static final @NonNull Parcelable.Creator<PollingFrame> CREATOR =
-            new Parcelable.Creator<>() {
-                @Override
-                public PollingFrame createFromParcel(Parcel source) {
-                    return new PollingFrame(source.readBundle());
-                }
-
-                @Override
-                public PollingFrame[] newArray(int size) {
-                    return new PollingFrame[size];
-                }
-            };
-
-    private PollingFrame(Bundle frame) {
-        mType = frame.getInt(KEY_POLLING_LOOP_TYPE);
-        byte[] data = frame.getByteArray(KEY_POLLING_LOOP_DATA);
-        mData = (data == null) ? new byte[0] : data;
-        mGain = frame.getInt(KEY_POLLING_LOOP_GAIN, -1);
-        mTimestamp = frame.getLong(KEY_POLLING_LOOP_TIMESTAMP);
-        mTriggeredAutoTransact = frame.containsKey(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT)
-                && frame.getBoolean(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT);
-    }
-
-    /**
-     * Constructor for Polling Frames.
-     *
-     * @param type the type of the frame
-     * @param data a byte array of the data contained in the frame
-     * @param gain the vendor-specific gain of the field
-     * @param timestampMicros the timestamp in microseconds
-     * @param triggeredAutoTransact whether or not this frame triggered the device to start a
-     * transaction automatically
-     *
-     * @hide
-     */
-    public PollingFrame(@PollingFrameType int type, @Nullable byte[] data,
-            int gain, long timestampMicros, boolean triggeredAutoTransact) {
-        mType = type;
-        mData = data == null ? new byte[0] : data;
-        mGain = gain;
-        mTimestamp = timestampMicros;
-        mTriggeredAutoTransact = triggeredAutoTransact;
-    }
-
-    /**
-     * Returns the type of frame for this polling loop frame.
-     * The possible return values are:
-     * <ul>
-     *   <li>{@link #POLLING_LOOP_TYPE_ON}</li>
-     *   <li>{@link #POLLING_LOOP_TYPE_OFF}</li>
-     *   <li>{@link #POLLING_LOOP_TYPE_A}</li>
-     *   <li>{@link #POLLING_LOOP_TYPE_B}</li>
-     *   <li>{@link #POLLING_LOOP_TYPE_F}</li>
-     * </ul>
-     */
-    public @PollingFrameType int getType() {
-        return mType;
-    }
-
-    /**
-     * Returns the raw data from the polling type frame.
-     */
-    public @NonNull byte[] getData() {
-        return mData;
-    }
-
-    /**
-     * Returns the gain representing the field strength of the NFC field when this polling loop
-     * frame was observed.
-     * @return the gain or -1 if there is no gain measurement associated with this frame.
-     */
-    public int getVendorSpecificGain() {
-        return mGain;
-    }
-
-    /**
-     * Returns the timestamp of when the polling loop frame was observed, in microseconds. These
-     * timestamps are relative and should only be used for comparing the timing of frames relative
-     * to each other.
-     * @return the timestamp in microseconds
-     */
-    public long getTimestamp() {
-        return mTimestamp;
-    }
-
-    /**
-     * @hide
-     */
-    public void setTriggeredAutoTransact(boolean triggeredAutoTransact) {
-        mTriggeredAutoTransact = triggeredAutoTransact;
-    }
-
-    /**
-     * Returns whether this frame triggered the device to automatically disable observe mode and
-     * allow one transaction.
-     */
-    public boolean getTriggeredAutoTransact() {
-        return mTriggeredAutoTransact;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeBundle(toBundle());
-    }
-
-    /**
-     * @return a Bundle representing this frame
-     */
-    private Bundle toBundle() {
-        Bundle frame = new Bundle();
-        frame.putInt(KEY_POLLING_LOOP_TYPE, getType());
-        if (getVendorSpecificGain() != -1) {
-            frame.putInt(KEY_POLLING_LOOP_GAIN, (byte) getVendorSpecificGain());
-        }
-        frame.putByteArray(KEY_POLLING_LOOP_DATA, getData());
-        frame.putLong(KEY_POLLING_LOOP_TIMESTAMP, getTimestamp());
-        frame.putBoolean(KEY_POLLING_LOOP_TRIGGERED_AUTOTRANSACT, getTriggeredAutoTransact());
-        return frame;
-    }
-
-    @Override
-    public String toString() {
-        return "PollingFrame { Type: " + (char) getType()
-                + ", gain: " + getVendorSpecificGain()
-                + ", timestamp: " + Long.toUnsignedString(getTimestamp())
-                + ", data: [" + HexFormat.ofDelimiter(" ").formatHex(getData()) + "] }";
-    }
-}
diff --git a/nfc/java/android/nfc/cardemulation/Utils.java b/nfc/java/android/nfc/cardemulation/Utils.java
deleted file mode 100644
index 202e1cf..0000000
--- a/nfc/java/android/nfc/cardemulation/Utils.java
+++ /dev/null
@@ -1,37 +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.nfc.cardemulation;
-
-import android.annotation.NonNull;
-import android.content.ComponentName;
-import android.content.ComponentNameProto;
-import android.util.proto.ProtoOutputStream;
-
-/** @hide */
-public final class Utils {
-    private Utils() {
-    }
-
-    /** Copied from {@link ComponentName#dumpDebug(ProtoOutputStream, long)} */
-    public static void dumpDebugComponentName(
-            @NonNull ComponentName componentName, @NonNull ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        proto.write(ComponentNameProto.PACKAGE_NAME, componentName.getPackageName());
-        proto.write(ComponentNameProto.CLASS_NAME, componentName.getClassName());
-        proto.end(token);
-    }
-}
diff --git a/nfc/java/android/nfc/dta/NfcDta.java b/nfc/java/android/nfc/dta/NfcDta.java
deleted file mode 100644
index 8801662..0000000
--- a/nfc/java/android/nfc/dta/NfcDta.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.dta;
-
-import android.content.Context;
-import android.nfc.INfcDta;
-import android.nfc.NfcAdapter;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.HashMap;
-
-/**
- * This class provides the primary API for DTA operations.
- * @hide
- */
-public final class NfcDta {
-    private static final String TAG = "NfcDta";
-
-    private static INfcDta sService;
-    private static HashMap<Context, NfcDta> sNfcDtas = new HashMap<Context, NfcDta>();
-
-    private final Context mContext;
-
-    private NfcDta(Context context, INfcDta service) {
-        mContext = context.getApplicationContext();
-        sService = service;
-    }
-
-    /**
-     * Helper to get an instance of this class.
-     *
-     * @param adapter A reference to an NfcAdapter object.
-     * @return
-     */
-    public static synchronized NfcDta getInstance(NfcAdapter adapter) {
-        if (adapter == null) throw new NullPointerException("NfcAdapter is null");
-        Context context = adapter.getContext();
-        if (context == null) {
-            Log.e(TAG, "NfcAdapter context is null.");
-            throw new UnsupportedOperationException();
-        }
-
-        NfcDta manager = sNfcDtas.get(context);
-        if (manager == null) {
-            INfcDta service = adapter.getNfcDtaInterface();
-            if (service == null) {
-                Log.e(TAG, "This device does not implement the INfcDta interface.");
-                throw new UnsupportedOperationException();
-            }
-            manager = new NfcDta(context, service);
-            sNfcDtas.put(context, manager);
-        }
-        return manager;
-    }
-
-    /**
-     * Enables DTA mode
-     *
-     * @return true/false if enabling was successful
-     */
-    public boolean enableDta() {
-        try {
-            sService.enableDta();
-        } catch (RemoteException e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Disables DTA mode
-     *
-     * @return true/false if disabling was successful
-     */
-    public boolean disableDta() {
-        try {
-            sService.disableDta();
-        } catch (RemoteException e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Enables Server
-     *
-     * @return true/false if enabling was successful
-     */
-    public boolean enableServer(String serviceName, int serviceSap, int miu,
-            int rwSize, int testCaseId) {
-        try {
-            return sService.enableServer(serviceName, serviceSap, miu, rwSize, testCaseId);
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Disables Server
-     *
-     * @return true/false if disabling was successful
-     */
-    public boolean disableServer() {
-        try {
-            sService.disableServer();
-        } catch (RemoteException e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Enables Client
-     *
-     * @return true/false if enabling was successful
-     */
-    public boolean enableClient(String serviceName, int miu, int rwSize,
-            int testCaseId) {
-        try {
-            return sService.enableClient(serviceName, miu, rwSize, testCaseId);
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Disables client
-     *
-     * @return true/false if disabling was successful
-     */
-    public boolean disableClient() {
-        try {
-            sService.disableClient();
-        } catch (RemoteException e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Registers Message Service
-     *
-     * @return true/false if registration was successful
-     */
-    public boolean registerMessageService(String msgServiceName) {
-        try {
-            return sService.registerMessageService(msgServiceName);
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/package.html b/nfc/java/android/nfc/package.html
deleted file mode 100644
index 55c1d16..0000000
--- a/nfc/java/android/nfc/package.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<HTML>
-<BODY>
-<p>Provides access to Near Field Communication (NFC) functionality, allowing applications to read
-NDEF message in NFC tags. A "tag" may actually be another device that appears as a tag.</p>
-
-<p>For more information, see the
-<a href="{@docRoot}guide/topics/connectivity/nfc/index.html">Near Field Communication</a> guide.</p>
-{@more}
-
-<p>Here's a summary of the classes:</p>
-
-<dl>
-  <dt>{@link android.nfc.NfcManager}</dt>
-  <dd>This is the high level manager, used to obtain this device's {@link android.nfc.NfcAdapter}. You can
-acquire an instance using {@link android.content.Context#getSystemService}.</dd>
-  <dt>{@link android.nfc.NfcAdapter}</dt>
-  <dd>This represents the device's NFC adapter, which is your entry-point to performing NFC
-operations. You can acquire an instance with {@link android.nfc.NfcManager#getDefaultAdapter}, or
-{@link android.nfc.NfcAdapter#getDefaultAdapter(android.content.Context)}.</dd>
-  <dt>{@link android.nfc.NdefMessage}</dt>
-  <dd>Represents an NDEF data message, which is the standard format in which "records"
-carrying data are transmitted between devices and tags. Your application can receive these
-messages from an {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED} intent.</dd>
-  <dt>{@link android.nfc.NdefRecord}</dt>
-  <dd>Represents a record, which is delivered in a {@link android.nfc.NdefMessage} and describes the
-type of data being shared and carries the data itself.</dd>
-</dl>
-
-<p class="note"><strong>Note:</strong>
-Not all Android-powered devices provide NFC functionality.</p>
-
-</BODY>
-</HTML>
diff --git a/nfc/java/android/nfc/tech/BasicTagTechnology.java b/nfc/java/android/nfc/tech/BasicTagTechnology.java
deleted file mode 100644
index ae468fe..0000000
--- a/nfc/java/android/nfc/tech/BasicTagTechnology.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.nfc.TransceiveResult;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * A base class for tag technologies that are built on top of transceive().
- */
-abstract class BasicTagTechnology implements TagTechnology {
-    private static final String TAG = "NFC";
-
-    final Tag mTag;
-
-    boolean mIsConnected;
-    int mSelectedTechnology;
-
-    BasicTagTechnology(Tag tag, int tech) throws RemoteException {
-        mTag = tag;
-        mSelectedTechnology = tech;
-    }
-
-    @Override
-    public Tag getTag() {
-        return mTag;
-    }
-
-    /** Internal helper to throw IllegalStateException if the technology isn't connected */
-    void checkConnected() {
-       if ((mTag.getConnectedTechnology() != mSelectedTechnology) ||
-               (mTag.getConnectedTechnology() == -1)) {
-           throw new IllegalStateException("Call connect() first!");
-       }
-    }
-
-    @Override
-    public boolean isConnected() {
-        if (!mIsConnected) {
-            return false;
-        }
-
-        try {
-            return mTag.getTagService().isPresent(mTag.getServiceHandle());
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return false;
-        }
-    }
-
-    @Override
-    public void connect() throws IOException {
-        try {
-            int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(),
-                    mSelectedTechnology);
-
-            if (errorCode == ErrorCodes.SUCCESS) {
-                // Store this in the tag object
-                if (!mTag.setConnectedTechnology(mSelectedTechnology)) {
-                    Log.e(TAG, "Close other technology first!");
-                    throw new IOException("Only one TagTechnology can be connected at a time.");
-                }
-                mIsConnected = true;
-            } else if (errorCode == ErrorCodes.ERROR_NOT_SUPPORTED) {
-                throw new UnsupportedOperationException("Connecting to " +
-                        "this technology is not supported by the NFC " +
-                        "adapter.");
-            } else {
-                throw new IOException();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            throw new IOException("NFC service died");
-        }
-    }
-
-    /** @hide */
-    @Override
-    public void reconnect() throws IOException {
-        if (!mIsConnected) {
-            throw new IllegalStateException("Technology not connected yet");
-        }
-
-        try {
-            int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
-
-            if (errorCode != ErrorCodes.SUCCESS) {
-                mIsConnected = false;
-                mTag.setTechnologyDisconnected();
-                throw new IOException();
-            }
-        } catch (RemoteException e) {
-            mIsConnected = false;
-            mTag.setTechnologyDisconnected();
-            Log.e(TAG, "NFC service dead", e);
-            throw new IOException("NFC service died");
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        try {
-            /* Note that we don't want to physically disconnect the tag,
-             * but just reconnect to it to reset its state
-             */
-            mTag.getTagService().resetTimeouts();
-            mTag.getTagService().reconnect(mTag.getServiceHandle());
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        } finally {
-            mIsConnected = false;
-            mTag.setTechnologyDisconnected();
-        }
-    }
-
-    /** Internal getMaxTransceiveLength() */
-    int getMaxTransceiveLengthInternal() {
-        try {
-            return mTag.getTagService().getMaxTransceiveLength(mSelectedTechnology);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-    /** Internal transceive */
-    byte[] transceive(byte[] data, boolean raw) throws IOException {
-        checkConnected();
-
-        try {
-            TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(),
-                    data, raw);
-            if (result == null) {
-                throw new IOException("transceive failed");
-            } else {
-                return result.getResponseOrThrow();
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            throw new IOException("NFC service died");
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/IsoDep.java b/nfc/java/android/nfc/tech/IsoDep.java
deleted file mode 100644
index 0ba0c5a..0000000
--- a/nfc/java/android/nfc/tech/IsoDep.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire an {@link IsoDep} object using {@link #get}.
- * <p>The primary ISO-DEP I/O operation is {@link #transceive}. Applications must
- * implement their own protocol stack on top of {@link #transceive}.
- * <p>Tags that enumerate the {@link IsoDep} technology in {@link Tag#getTechList}
- * will also enumerate
- * {@link NfcA} or {@link NfcB} (since IsoDep builds on top of either of these).
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class IsoDep extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /** @hide */
-    public static final String EXTRA_HI_LAYER_RESP = "hiresp";
-    /** @hide */
-    public static final String EXTRA_HIST_BYTES = "histbytes";
-
-    private byte[] mHiLayerResponse = null;
-    private byte[] mHistBytes = null;
-
-    /**
-     * Get an instance of {@link IsoDep} for the given tag.
-     * <p>Does not cause any RF activity and does not block.
-     * <p>Returns null if {@link IsoDep} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag does not support ISO-DEP.
-     *
-     * @param tag an ISO-DEP compatible tag
-     * @return ISO-DEP object
-     */
-    public static IsoDep get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.ISO_DEP)) return null;
-        try {
-            return new IsoDep(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public IsoDep(Tag tag)
-            throws RemoteException {
-        super(tag, TagTechnology.ISO_DEP);
-        Bundle extras = tag.getTechExtras(TagTechnology.ISO_DEP);
-        if (extras != null) {
-            mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
-            mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
-        }
-    }
-
-    /**
-     * Set the timeout of {@link #transceive} in milliseconds.
-     * <p>The timeout only applies to ISO-DEP {@link #transceive}, and is
-     * reset to a default value when {@link #close} is called.
-     * <p>Setting a longer timeout may be useful when performing
-     * transactions that require a long processing time on the tag
-     * such as key generation.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param timeout timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void setTimeout(int timeout) {
-        try {
-            int err = mTag.getTagService().setTimeout(TagTechnology.ISO_DEP, timeout);
-            if (err != ErrorCodes.SUCCESS) {
-                throw new IllegalArgumentException("The supplied timeout is not valid");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Get the current timeout for {@link #transceive} in milliseconds.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public int getTimeout() {
-        try {
-            return mTag.getTagService().getTimeout(TagTechnology.ISO_DEP);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-
-    /**
-     * Return the ISO-DEP historical bytes for {@link NfcA} tags.
-     * <p>Does not cause any RF activity and does not block.
-     * <p>The historical bytes can be used to help identify a tag. They are present
-     * only on {@link IsoDep} tags that are based on {@link NfcA} RF technology.
-     * If this tag is not {@link NfcA} then null is returned.
-     * <p>In ISO 14443-4 terminology, the historical bytes are a subset of the RATS
-     * response.
-     *
-     * @return ISO-DEP historical bytes, or null if this is not a {@link NfcA} tag
-     */
-    public byte[] getHistoricalBytes() {
-        return mHistBytes;
-    }
-
-    /**
-     * Return the higher layer response bytes for {@link NfcB} tags.
-     * <p>Does not cause any RF activity and does not block.
-     * <p>The higher layer response bytes can be used to help identify a tag.
-     * They are present only on {@link IsoDep} tags that are based on {@link NfcB}
-     * RF technology. If this tag is not {@link NfcB} then null is returned.
-     * <p>In ISO 14443-4 terminology, the higher layer bytes are a subset of the
-     * ATTRIB response.
-     *
-     * @return ISO-DEP historical bytes, or null if this is not a {@link NfcB} tag
-     */
-    public byte[] getHiLayerResponse() {
-        return mHiLayerResponse;
-    }
-
-    /**
-     * Send raw ISO-DEP data to the tag and receive the response.
-     *
-     * <p>Applications must only send the INF payload, and not the start of frame and
-     * end of frame indicators. Applications do not need to fragment the payload, it
-     * will be automatically fragmented and defragmented by {@link #transceive} if
-     * it exceeds FSD/FSC limits.
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data command bytes to send, must not be null
-     * @return response bytes received, will not be null
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or this operation is canceled
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-
-    /**
-     * <p>Standard APDUs have a 1-byte length field, allowing a maximum of
-     * 255 payload bytes, which results in a maximum APDU length of 261 bytes.
-     *
-     * <p>Extended length APDUs have a 3-byte length field, allowing 65535
-     * payload bytes.
-     *
-     * <p>Some NFC adapters, like the one used in the Nexus S and the Galaxy Nexus
-     * do not support extended length APDUs. They are expected to be well-supported
-     * in the future though. Use this method to check for extended length APDU
-     * support.
-     *
-     * @return whether the NFC adapter on this device supports extended length APDUs.
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public boolean isExtendedLengthApduSupported() {
-        try {
-            return mTag.getTagService().getExtendedLengthApdusSupported();
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return false;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/MifareClassic.java b/nfc/java/android/nfc/tech/MifareClassic.java
deleted file mode 100644
index 26f54e6..0000000
--- a/nfc/java/android/nfc/tech/MifareClassic.java
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Provides access to MIFARE Classic properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link MifareClassic} object using {@link #get}.
- *
- * <p>MIFARE Classic is also known as MIFARE Standard.
- * <p>MIFARE Classic tags are divided into sectors, and each sector is sub-divided into
- * blocks. Block size is always 16 bytes ({@link #BLOCK_SIZE}. Sector size varies.
- * <ul>
- * <li>MIFARE Classic Mini are 320 bytes ({@link #SIZE_MINI}), with 5 sectors each of 4 blocks.
- * <li>MIFARE Classic 1k are 1024 bytes ({@link #SIZE_1K}), with 16 sectors each of 4 blocks.
- * <li>MIFARE Classic 2k are 2048 bytes ({@link #SIZE_2K}), with 32 sectors each of 4 blocks.
- * <li>MIFARE Classic 4k are 4096 bytes ({@link #SIZE_4K}). The first 32 sectors contain 4 blocks
- * and the last 8 sectors contain 16 blocks.
- * </ul>
- *
- * <p>MIFARE Classic tags require authentication on a per-sector basis before any
- * other I/O operations on that sector can be performed. There are two keys per sector,
- * and ACL bits determine what I/O operations are allowed on that sector after
- * authenticating with a key. {@see #authenticateSectorWithKeyA} and
- * {@see #authenticateSectorWithKeyB}.
- *
- * <p>Three well-known authentication keys are defined in this class:
- * {@link #KEY_DEFAULT}, {@link #KEY_MIFARE_APPLICATION_DIRECTORY},
- * {@link #KEY_NFC_FORUM}.
- * <ul>
- * <li>{@link #KEY_DEFAULT} is the default factory key for MIFARE Classic.
- * <li>{@link #KEY_MIFARE_APPLICATION_DIRECTORY} is the well-known key for
- * MIFARE Classic cards that have been formatted according to the
- * MIFARE Application Directory (MAD) specification.
- * <li>{@link #KEY_NFC_FORUM} is the well-known key for MIFARE Classic cards that
- * have been formatted according to the NXP specification for NDEF on MIFARE Classic.
- *
- * <p>Implementation of this class on a Android NFC device is optional.
- * If it is not implemented, then
- * {@link MifareClassic} will never be enumerated in {@link Tag#getTechList}.
- * If it is enumerated, then all {@link MifareClassic} I/O operations will be supported,
- * and {@link Ndef#MIFARE_CLASSIC} NDEF tags will also be supported. In either case,
- * {@link NfcA} will also be enumerated on the tag, because all MIFARE Classic tags are also
- * {@link NfcA}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class MifareClassic extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /**
-     * The default factory key.
-     */
-    public static final byte[] KEY_DEFAULT =
-            {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
-    /**
-     * The well-known key for tags formatted according to the
-     * MIFARE Application Directory (MAD) specification.
-     */
-    public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
-            {(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
-    /**
-     * The well-known key for tags formatted according to the
-     * NDEF on MIFARE Classic specification.
-     */
-    public static final byte[] KEY_NFC_FORUM =
-            {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
-
-    /** A MIFARE Classic compatible card of unknown type */
-    public static final int TYPE_UNKNOWN = -1;
-    /** A MIFARE Classic tag */
-    public static final int TYPE_CLASSIC = 0;
-    /** A MIFARE Plus tag */
-    public static final int TYPE_PLUS = 1;
-    /** A MIFARE Pro tag */
-    public static final int TYPE_PRO = 2;
-
-    /** Tag contains 16 sectors, each with 4 blocks. */
-    public static final int SIZE_1K = 1024;
-    /** Tag contains 32 sectors, each with 4 blocks. */
-    public static final int SIZE_2K = 2048;
-    /**
-     * Tag contains 40 sectors. The first 32 sectors contain 4 blocks and the last 8 sectors
-     * contain 16 blocks.
-     */
-    public static final int SIZE_4K = 4096;
-    /** Tag contains 5 sectors, each with 4 blocks. */
-    public static final int SIZE_MINI = 320;
-
-    /** Size of a MIFARE Classic block (in bytes) */
-    public static final int BLOCK_SIZE = 16;
-
-    private static final int MAX_BLOCK_COUNT = 256;
-    private static final int MAX_SECTOR_COUNT = 40;
-
-    private boolean mIsEmulated;
-    private int mType;
-    private int mSize;
-
-    /**
-     * Get an instance of {@link MifareClassic} for the given tag.
-     * <p>Does not cause any RF activity and does not block.
-     * <p>Returns null if {@link MifareClassic} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag is not MIFARE Classic compatible, or this Android
-     * device does not support MIFARE Classic.
-     *
-     * @param tag an MIFARE Classic compatible tag
-     * @return MIFARE Classic object
-     */
-    public static MifareClassic get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.MIFARE_CLASSIC)) return null;
-        try {
-            return new MifareClassic(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public MifareClassic(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.MIFARE_CLASSIC);
-
-        NfcA a = NfcA.get(tag);  // MIFARE Classic is always based on NFC a
-
-        mIsEmulated = false;
-
-        switch (a.getSak()) {
-        case 0x01:
-        case 0x08:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_1K;
-            break;
-        case 0x09:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_MINI;
-            break;
-        case 0x10:
-            mType = TYPE_PLUS;
-            mSize = SIZE_2K;
-            // SecLevel = SL2
-            break;
-        case 0x11:
-            mType = TYPE_PLUS;
-            mSize = SIZE_4K;
-            // Seclevel = SL2
-            break;
-        case 0x18:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_4K;
-            break;
-        case 0x28:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_1K;
-            mIsEmulated = true;
-            break;
-        case 0x38:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_4K;
-            mIsEmulated = true;
-            break;
-        case 0x88:
-            mType = TYPE_CLASSIC;
-            mSize = SIZE_1K;
-            // NXP-tag: false
-            break;
-        case 0x98:
-        case 0xB8:
-            mType = TYPE_PRO;
-            mSize = SIZE_4K;
-            break;
-        default:
-            // Stack incorrectly reported a MifareClassic. We cannot handle this
-            // gracefully - we have no idea of the memory layout. Bail.
-            throw new RuntimeException(
-                    "Tag incorrectly enumerated as MIFARE Classic, SAK = " + a.getSak());
-        }
-    }
-
-    /**
-     * Return the type of this MIFARE Classic compatible tag.
-     * <p>One of {@link #TYPE_UNKNOWN}, {@link #TYPE_CLASSIC}, {@link #TYPE_PLUS} or
-     * {@link #TYPE_PRO}.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return type
-     */
-    public int getType() {
-        return mType;
-    }
-
-    /**
-     * Return the size of the tag in bytes
-     * <p>One of {@link #SIZE_MINI}, {@link #SIZE_1K}, {@link #SIZE_2K}, {@link #SIZE_4K}.
-     * These constants are equal to their respective size in bytes.
-     * <p>Does not cause any RF activity and does not block.
-     * @return size in bytes
-     */
-    public int getSize() {
-        return mSize;
-    }
-
-    /**
-     * Return true if the tag is emulated, determined at discovery time.
-     * These are actually smart-cards that emulate a MIFARE Classic interface.
-     * They can be treated identically to a MIFARE Classic tag.
-     * @hide
-     */
-    public boolean isEmulated() {
-        return mIsEmulated;
-    }
-
-    /**
-     * Return the number of MIFARE Classic sectors.
-     * <p>Does not cause any RF activity and does not block.
-     * @return number of sectors
-     */
-    public int getSectorCount() {
-        switch (mSize) {
-        case SIZE_1K:
-            return 16;
-        case SIZE_2K:
-            return 32;
-        case SIZE_4K:
-            return 40;
-        case SIZE_MINI:
-            return 5;
-        default:
-            return 0;
-        }
-    }
-
-    /**
-     * Return the total number of MIFARE Classic blocks.
-     * <p>Does not cause any RF activity and does not block.
-     * @return total number of blocks
-     */
-    public int getBlockCount() {
-        return mSize / BLOCK_SIZE;
-    }
-
-    /**
-     * Return the number of blocks in the given sector.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param sectorIndex index of sector, starting from 0
-     * @return number of blocks in the sector
-     */
-    public int getBlockCountInSector(int sectorIndex) {
-        validateSector(sectorIndex);
-
-        if (sectorIndex < 32) {
-            return 4;
-        } else {
-            return 16;
-        }
-    }
-
-    /**
-     * Return the sector that contains a given block.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param blockIndex index of block to lookup, starting from 0
-     * @return sector index that contains the block
-     */
-    public int blockToSector(int blockIndex) {
-        validateBlock(blockIndex);
-
-        if (blockIndex < 32 * 4) {
-            return blockIndex / 4;
-        } else {
-            return 32 + (blockIndex - 32 * 4) / 16;
-        }
-    }
-
-    /**
-     * Return the first block of a given sector.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param sectorIndex index of sector to lookup, starting from 0
-     * @return block index of first block in sector
-     */
-    public int sectorToBlock(int sectorIndex) {
-        if (sectorIndex < 32) {
-            return sectorIndex * 4;
-        } else {
-            return 32 * 4 + (sectorIndex - 32) * 16;
-        }
-    }
-
-    /**
-     * Authenticate a sector with key A.
-     *
-     * <p>Successful authentication of a sector with key A enables other
-     * I/O operations on that sector. The set of operations granted by key A
-     * key depends on the ACL bits set in that sector. For more information
-     * see the MIFARE Classic specification on <a href="http://www.nxp.com">http://www.nxp.com</a>.
-     *
-     * <p>A failed authentication attempt causes an implicit reconnection to the
-     * tag, so authentication to other sectors will be lost.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param sectorIndex index of sector to authenticate, starting from 0
-     * @param key 6-byte authentication key
-     * @return true on success, false on authentication failure
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public boolean authenticateSectorWithKeyA(int sectorIndex, byte[] key) throws IOException {
-        return authenticate(sectorIndex, key, true);
-    }
-
-    /**
-     * Authenticate a sector with key B.
-     *
-     * <p>Successful authentication of a sector with key B enables other
-     * I/O operations on that sector. The set of operations granted by key B
-     * depends on the ACL bits set in that sector. For more information
-     * see the MIFARE Classic specification on <a href="http://www.nxp.com">http://www.nxp.com</a>.
-     *
-     * <p>A failed authentication attempt causes an implicit reconnection to the
-     * tag, so authentication to other sectors will be lost.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param sectorIndex index of sector to authenticate, starting from 0
-     * @param key 6-byte authentication key
-     * @return true on success, false on authentication failure
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public boolean authenticateSectorWithKeyB(int sectorIndex, byte[] key) throws IOException {
-        return authenticate(sectorIndex, key, false);
-    }
-
-    private boolean authenticate(int sector, byte[] key, boolean keyA) throws IOException {
-        validateSector(sector);
-        checkConnected();
-
-        byte[] cmd = new byte[12];
-
-        // First byte is the command
-        if (keyA) {
-            cmd[0] = 0x60; // phHal_eMifareAuthentA
-        } else {
-            cmd[0] = 0x61; // phHal_eMifareAuthentB
-        }
-
-        // Second byte is block address
-        // Authenticate command takes a block address. Authenticating a block
-        // of a sector will authenticate the entire sector.
-        cmd[1] = (byte) sectorToBlock(sector);
-
-        // Next 4 bytes are last 4 bytes of UID
-        byte[] uid = getTag().getId();
-        System.arraycopy(uid, uid.length - 4, cmd, 2, 4);
-
-        // Next 6 bytes are key
-        System.arraycopy(key, 0, cmd, 6, 6);
-
-        try {
-            if (transceive(cmd, false) != null) {
-                return true;
-            }
-        } catch (TagLostException e) {
-            throw e;
-        } catch (IOException e) {
-            // No need to deal with, will return false anyway
-        }
-        return false;
-    }
-
-    /**
-     * Read 16-byte block.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to read, starting from 0
-     * @return 16 byte block
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public byte[] readBlock(int blockIndex) throws IOException {
-        validateBlock(blockIndex);
-        checkConnected();
-
-        byte[] cmd = { 0x30, (byte) blockIndex };
-        return transceive(cmd, false);
-    }
-
-    /**
-     * Write 16-byte block.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to write, starting from 0
-     * @param data 16 bytes of data to write
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void writeBlock(int blockIndex, byte[] data) throws IOException {
-        validateBlock(blockIndex);
-        checkConnected();
-        if (data.length != 16) {
-            throw new IllegalArgumentException("must write 16-bytes");
-        }
-
-        byte[] cmd = new byte[data.length + 2];
-        cmd[0] = (byte) 0xA0; // MF write command
-        cmd[1] = (byte) blockIndex;
-        System.arraycopy(data, 0, cmd, 2, data.length);
-
-        transceive(cmd, false);
-    }
-
-    /**
-     * Increment a value block, storing the result in the temporary block on the tag.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to increment, starting from 0
-     * @param value non-negative to increment by
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void increment(int blockIndex, int value) throws IOException {
-        validateBlock(blockIndex);
-        validateValueOperand(value);
-        checkConnected();
-
-        ByteBuffer cmd = ByteBuffer.allocate(6);
-        cmd.order(ByteOrder.LITTLE_ENDIAN);
-        cmd.put( (byte) 0xC1 );
-        cmd.put( (byte) blockIndex );
-        cmd.putInt(value);
-
-        transceive(cmd.array(), false);
-    }
-
-    /**
-     * Decrement a value block, storing the result in the temporary block on the tag.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to decrement, starting from 0
-     * @param value non-negative to decrement by
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void decrement(int blockIndex, int value) throws IOException {
-        validateBlock(blockIndex);
-        validateValueOperand(value);
-        checkConnected();
-
-        ByteBuffer cmd = ByteBuffer.allocate(6);
-        cmd.order(ByteOrder.LITTLE_ENDIAN);
-        cmd.put( (byte) 0xC0 );
-        cmd.put( (byte) blockIndex );
-        cmd.putInt(value);
-
-        transceive(cmd.array(), false);
-    }
-
-    /**
-     * Copy from the temporary block to a value block.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to copy to
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void transfer(int blockIndex) throws IOException {
-        validateBlock(blockIndex);
-        checkConnected();
-
-        byte[] cmd = { (byte) 0xB0, (byte) blockIndex };
-
-        transceive(cmd, false);
-    }
-
-    /**
-     * Copy from a value block to the temporary block.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param blockIndex index of block to copy from
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void restore(int blockIndex) throws IOException {
-        validateBlock(blockIndex);
-        checkConnected();
-
-        byte[] cmd = { (byte) 0xC2, (byte) blockIndex };
-
-        transceive(cmd, false);
-    }
-
-    /**
-     * Send raw NfcA data to a tag and receive the response.
-     *
-     * <p>This is equivalent to connecting to this tag via {@link NfcA}
-     * and calling {@link NfcA#transceive}. Note that all MIFARE Classic
-     * tags are based on {@link NfcA} technology.
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @see NfcA#transceive
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-
-    /**
-     * Set the {@link #transceive} timeout in milliseconds.
-     *
-     * <p>The timeout only applies to {@link #transceive} on this object,
-     * and is reset to a default value when {@link #close} is called.
-     *
-     * <p>Setting a longer timeout may be useful when performing
-     * transactions that require a long processing time on the tag
-     * such as key generation.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param timeout timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void setTimeout(int timeout) {
-        try {
-            int err = mTag.getTagService().setTimeout(TagTechnology.MIFARE_CLASSIC, timeout);
-            if (err != ErrorCodes.SUCCESS) {
-                throw new IllegalArgumentException("The supplied timeout is not valid");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Get the current {@link #transceive} timeout in milliseconds.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public int getTimeout() {
-        try {
-            return mTag.getTagService().getTimeout(TagTechnology.MIFARE_CLASSIC);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-
-    private static void validateSector(int sector) {
-        // Do not be too strict on upper bounds checking, since some cards
-        // have more addressable memory than they report. For example,
-        // MIFARE Plus 2k cards will appear as MIFARE Classic 1k cards when in
-        // MIFARE Classic compatibility mode.
-        // Note that issuing a command to an out-of-bounds block is safe - the
-        // tag should report error causing IOException. This validation is a
-        // helper to guard against obvious programming mistakes.
-        if (sector < 0 || sector >= MAX_SECTOR_COUNT) {
-            throw new IndexOutOfBoundsException("sector out of bounds: " + sector);
-        }
-    }
-
-    private static void validateBlock(int block) {
-        // Just looking for obvious out of bounds...
-        if (block < 0 || block >= MAX_BLOCK_COUNT) {
-            throw new IndexOutOfBoundsException("block out of bounds: " + block);
-        }
-    }
-
-    private static void validateValueOperand(int value) {
-        if (value < 0) {
-            throw new IllegalArgumentException("value operand negative");
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/MifareUltralight.java b/nfc/java/android/nfc/tech/MifareUltralight.java
deleted file mode 100644
index c0416a3..0000000
--- a/nfc/java/android/nfc/tech/MifareUltralight.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-//TOOD: Ultralight C 3-DES authentication, one-way counter
-
-/**
- * Provides access to MIFARE Ultralight properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link MifareUltralight} object using {@link #get}.
- *
- * <p>MIFARE Ultralight compatible tags have 4 byte pages {@link #PAGE_SIZE}.
- * The primary operations on an Ultralight tag are {@link #readPages} and
- * {@link #writePage}.
- *
- * <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first
- * 4 pages are for the OTP area, manufacturer data, and locking bits. They are
- * readable and some bits are writable. The final 12 pages are the user
- * read/write area. For more information see the NXP data sheet MF0ICU1.
- *
- * <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages
- * are for OTP, manufacturer data, and locking bits. The next 36 pages are the
- * user read/write area. The next 4 pages are additional locking bits, counters
- * and authentication configuration and are readable. The final 4 pages are for
- * the authentication key and are not readable. For more information see the
- * NXP data sheet MF0ICU2.
- *
- * <p>Implementation of this class on a Android NFC device is optional.
- * If it is not implemented, then
- * {@link MifareUltralight} will never be enumerated in {@link Tag#getTechList}.
- * If it is enumerated, then all {@link MifareUltralight} I/O operations will be supported.
- * In either case, {@link NfcA} will also be enumerated on the tag,
- * because all MIFARE Ultralight tags are also {@link NfcA} tags.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class MifareUltralight extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /** A MIFARE Ultralight compatible tag of unknown type */
-    public static final int TYPE_UNKNOWN = -1;
-    /** A MIFARE Ultralight tag */
-    public static final int TYPE_ULTRALIGHT = 1;
-    /** A MIFARE Ultralight C tag */
-    public static final int TYPE_ULTRALIGHT_C = 2;
-
-    /** Size of a MIFARE Ultralight page in bytes */
-    public static final int PAGE_SIZE = 4;
-
-    private static final int NXP_MANUFACTURER_ID = 0x04;
-    private static final int MAX_PAGE_COUNT = 256;
-
-    /** @hide */
-    public static final String EXTRA_IS_UL_C = "isulc";
-
-    private int mType;
-
-    /**
-     * Get an instance of {@link MifareUltralight} for the given tag.
-     * <p>Returns null if {@link MifareUltralight} was not enumerated in
-     * {@link Tag#getTechList} - this indicates the tag is not MIFARE
-     * Ultralight compatible, or that this Android
-     * device does not implement MIFARE Ultralight.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an MIFARE Ultralight compatible tag
-     * @return MIFARE Ultralight object
-     */
-    public static MifareUltralight get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.MIFARE_ULTRALIGHT)) return null;
-        try {
-            return new MifareUltralight(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public MifareUltralight(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.MIFARE_ULTRALIGHT);
-
-        // Check if this could actually be a MIFARE
-        NfcA a = NfcA.get(tag);
-
-        mType = TYPE_UNKNOWN;
-
-        if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
-            Bundle extras = tag.getTechExtras(TagTechnology.MIFARE_ULTRALIGHT);
-            if (extras.getBoolean(EXTRA_IS_UL_C)) {
-                mType = TYPE_ULTRALIGHT_C;
-            } else {
-                mType = TYPE_ULTRALIGHT;
-            }
-        }
-    }
-
-    /**
-     * Return the MIFARE Ultralight type of the tag.
-     * <p>One of {@link #TYPE_ULTRALIGHT} or {@link #TYPE_ULTRALIGHT_C} or
-     * {@link #TYPE_UNKNOWN}.
-     * <p>Depending on how the tag has been formatted, it can be impossible
-     * to accurately classify between original MIFARE Ultralight and
-     * Ultralight C. So treat this method as a hint.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return the type
-     */
-    public int getType() {
-        return mType;
-    }
-
-    /**
-     * Read 4 pages (16 bytes).
-     *
-     * <p>The MIFARE Ultralight protocol always reads 4 pages at a time, to
-     * reduce the number of commands required to read an entire tag.
-     * <p>If a read spans past the last readable block, then the tag will
-     * return pages that have been wrapped back to the first blocks. MIFARE
-     * Ultralight tags have readable blocks 0x00 through 0x0F. So a read to
-     * block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE
-     * Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to
-     * block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param pageOffset index of first page to read, starting from 0
-     * @return 4 pages (16 bytes)
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public byte[] readPages(int pageOffset) throws IOException {
-        validatePageIndex(pageOffset);
-        checkConnected();
-
-        byte[] cmd = { 0x30, (byte) pageOffset};
-        return transceive(cmd, false);
-    }
-
-    /**
-     * Write 1 page (4 bytes).
-     *
-     * <p>The MIFARE Ultralight protocol always writes 1 page at a time, to
-     * minimize EEPROM write cycles.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param pageOffset index of page to write, starting from 0
-     * @param data 4 bytes to write
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     */
-    public void writePage(int pageOffset, byte[] data) throws IOException {
-        validatePageIndex(pageOffset);
-        checkConnected();
-
-        byte[] cmd = new byte[data.length + 2];
-        cmd[0] = (byte) 0xA2;
-        cmd[1] = (byte) pageOffset;
-        System.arraycopy(data, 0, cmd, 2, data.length);
-
-        transceive(cmd, false);
-    }
-
-    /**
-     * Send raw NfcA data to a tag and receive the response.
-     *
-     * <p>This is equivalent to connecting to this tag via {@link NfcA}
-     * and calling {@link NfcA#transceive}. Note that all MIFARE Classic
-     * tags are based on {@link NfcA} technology.
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @see NfcA#transceive
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-
-    /**
-     * Set the {@link #transceive} timeout in milliseconds.
-     *
-     * <p>The timeout only applies to {@link #transceive} on this object,
-     * and is reset to a default value when {@link #close} is called.
-     *
-     * <p>Setting a longer timeout may be useful when performing
-     * transactions that require a long processing time on the tag
-     * such as key generation.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param timeout timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void setTimeout(int timeout) {
-        try {
-            int err = mTag.getTagService().setTimeout(
-                    TagTechnology.MIFARE_ULTRALIGHT, timeout);
-            if (err != ErrorCodes.SUCCESS) {
-                throw new IllegalArgumentException("The supplied timeout is not valid");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Get the current {@link #transceive} timeout in milliseconds.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public int getTimeout() {
-        try {
-            return mTag.getTagService().getTimeout(TagTechnology.MIFARE_ULTRALIGHT);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-
-    private static void validatePageIndex(int pageIndex) {
-        // Do not be too strict on upper bounds checking, since some cards
-        // may have more addressable memory than they report.
-        // Note that issuing a command to an out-of-bounds block is safe - the
-        // tag will wrap the read to an addressable area. This validation is a
-        // helper to guard against obvious programming mistakes.
-        if (pageIndex < 0 || pageIndex >= MAX_PAGE_COUNT) {
-            throw new IndexOutOfBoundsException("page out of bounds: " + pageIndex);
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/Ndef.java b/nfc/java/android/nfc/tech/Ndef.java
deleted file mode 100644
index 7d83f15..0000000
--- a/nfc/java/android/nfc/tech/Ndef.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.FormatException;
-import android.nfc.INfcTag;
-import android.nfc.NdefMessage;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Provides access to NDEF content and operations on a {@link Tag}.
- *
- * <p>Acquire a {@link Ndef} object using {@link #get}.
- *
- * <p>NDEF is an NFC Forum data format. The data formats are implemented in
- * {@link android.nfc.NdefMessage} and
- * {@link android.nfc.NdefRecord}. This class provides methods to
- * retrieve and modify the {@link android.nfc.NdefMessage}
- * on a tag.
- *
- * <p>There are currently four NFC Forum standardized tag types that can be
- * formatted to contain NDEF data.
- * <ul>
- * <li>NFC Forum Type 1 Tag ({@link #NFC_FORUM_TYPE_1}), such as the Innovision Topaz
- * <li>NFC Forum Type 2 Tag ({@link #NFC_FORUM_TYPE_2}), such as the NXP MIFARE Ultralight
- * <li>NFC Forum Type 3 Tag ({@link #NFC_FORUM_TYPE_3}), such as Sony Felica
- * <li>NFC Forum Type 4 Tag ({@link #NFC_FORUM_TYPE_4}), such as NXP MIFARE Desfire
- * </ul>
- * It is mandatory for all Android devices with NFC to correctly enumerate
- * {@link Ndef} on NFC Forum Tag Types 1-4, and implement all NDEF operations
- * as defined in this class.
- *
- * <p>Some vendors have their own well defined specifications for storing NDEF data
- * on tags that do not fall into the above categories. Android devices with NFC
- * should enumerate and implement {@link Ndef} under these vendor specifications
- * where possible, but it is not mandatory. {@link #getType} returns a String
- * describing this specification, for example {@link #MIFARE_CLASSIC} is
- * <code>com.nxp.ndef.mifareclassic</code>.
- *
- * <p>Android devices that support MIFARE Classic must also correctly
- * implement {@link Ndef} on MIFARE Classic tags formatted to NDEF.
- *
- * <p>For guaranteed compatibility across all Android devices with NFC, it is
- * recommended to use NFC Forum Types 1-4 in new deployments of NFC tags
- * with NDEF payload. Vendor NDEF formats will not work on all Android devices.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class Ndef extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /** @hide */
-    public static final int NDEF_MODE_READ_ONLY = 1;
-    /** @hide */
-    public static final int NDEF_MODE_READ_WRITE = 2;
-    /** @hide */
-    public static final int NDEF_MODE_UNKNOWN = 3;
-
-    /** @hide */
-    public static final String EXTRA_NDEF_MSG = "ndefmsg";
-
-    /** @hide */
-    public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";
-
-    /** @hide */
-    public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";
-
-    /** @hide */
-    public static final String EXTRA_NDEF_TYPE = "ndeftype";
-
-    /** @hide */
-    public static final int TYPE_OTHER = -1;
-    /** @hide */
-    public static final int TYPE_1 = 1;
-    /** @hide */
-    public static final int TYPE_2 = 2;
-    /** @hide */
-    public static final int TYPE_3 = 3;
-    /** @hide */
-    public static final int TYPE_4 = 4;
-    /** @hide */
-    public static final int TYPE_MIFARE_CLASSIC = 101;
-    /** @hide */
-    public static final int TYPE_ICODE_SLI = 102;
-
-    /** @hide */
-    public static final String UNKNOWN = "android.ndef.unknown";
-
-    /** NFC Forum Tag Type 1 */
-    public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
-    /** NFC Forum Tag Type 2 */
-    public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
-    /** NFC Forum Tag Type 3 */
-    public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
-    /** NFC Forum Tag Type 4 */
-    public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
-    /** NDEF on MIFARE Classic */
-    public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
-    /**
-     * NDEF on iCODE SLI
-     * @hide
-     */
-    public static final String ICODE_SLI = "com.nxp.ndef.icodesli";
-
-    private final int mMaxNdefSize;
-    private final int mCardState;
-    private final NdefMessage mNdefMsg;
-    private final int mNdefType;
-
-    /**
-     * Get an instance of {@link Ndef} for the given tag.
-     *
-     * <p>Returns null if {@link Ndef} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag is not NDEF formatted, or that this tag
-     * is NDEF formatted but under a vendor specification that this Android
-     * device does not implement.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NDEF compatible tag
-     * @return Ndef object
-     */
-    public static Ndef get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NDEF)) return null;
-        try {
-            return new Ndef(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Internal constructor, to be used by NfcAdapter
-     * @hide
-     */
-    public Ndef(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NDEF);
-        Bundle extras = tag.getTechExtras(TagTechnology.NDEF);
-        if (extras != null) {
-            mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
-            mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
-            mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG, android.nfc.NdefMessage.class);
-            mNdefType = extras.getInt(EXTRA_NDEF_TYPE);
-        } else {
-            throw new NullPointerException("NDEF tech extras are null.");
-        }
-
-    }
-
-    /**
-     * Get the {@link NdefMessage} that was read from the tag at discovery time.
-     *
-     * <p>If the NDEF Message is modified by an I/O operation then it
-     * will not be updated here, this function only returns what was discovered
-     * when the tag entered the field.
-     * <p>Note that this method may return null if the tag was in the
-     * INITIALIZED state as defined by NFC Forum, as in this state the
-     * tag is formatted to support NDEF but does not contain a message yet.
-     * <p>Does not cause any RF activity and does not block.
-     * @return NDEF Message read from the tag at discovery time, can be null
-     */
-    public NdefMessage getCachedNdefMessage() {
-        return mNdefMsg;
-    }
-
-    /**
-     * Get the NDEF tag type.
-     *
-     * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
-     * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
-     * {@link #MIFARE_CLASSIC} or another NDEF tag type that has not yet been
-     * formalized in this Android API.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return a string representing the NDEF tag type
-     */
-    public String getType() {
-        switch (mNdefType) {
-            case TYPE_1:
-                return NFC_FORUM_TYPE_1;
-            case TYPE_2:
-                return NFC_FORUM_TYPE_2;
-            case TYPE_3:
-                return NFC_FORUM_TYPE_3;
-            case TYPE_4:
-                return NFC_FORUM_TYPE_4;
-            case TYPE_MIFARE_CLASSIC:
-                return MIFARE_CLASSIC;
-            case TYPE_ICODE_SLI:
-                return ICODE_SLI;
-            default:
-                return UNKNOWN;
-        }
-    }
-
-    /**
-     * Get the maximum NDEF message size in bytes.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return size in bytes
-     */
-    public int getMaxSize() {
-        return mMaxNdefSize;
-    }
-
-    /**
-     * Determine if the tag is writable.
-     *
-     * <p>NFC Forum tags can be in read-only or read-write states.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return true if the tag is writable
-     */
-    public boolean isWritable() {
-        return (mCardState == NDEF_MODE_READ_WRITE);
-    }
-
-    /**
-     * Read the current {@link android.nfc.NdefMessage} on this tag.
-     *
-     * <p>This always reads the current NDEF Message stored on the tag.
-     *
-     * <p>Note that this method may return null if the tag was in the
-     * INITIALIZED state as defined by NFC Forum, as in that state the
-     * tag is formatted to support NDEF but does not contain a message yet.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return the NDEF Message, can be null
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     * @throws FormatException if the NDEF Message on the tag is malformed
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public NdefMessage getNdefMessage() throws IOException, FormatException {
-        checkConnected();
-
-        try {
-            INfcTag tagService = mTag.getTagService();
-            if (tagService == null) {
-                throw new IOException("Mock tags don't support this operation.");
-            }
-            int serviceHandle = mTag.getServiceHandle();
-            if (tagService.isNdef(serviceHandle)) {
-                NdefMessage msg = tagService.ndefRead(serviceHandle);
-                if (msg == null && !tagService.isPresent(serviceHandle)) {
-                    throw new TagLostException();
-                }
-                return msg;
-            } else if (!tagService.isPresent(serviceHandle)) {
-                throw new TagLostException();
-            } else {
-                return null;
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return null;
-        }
-    }
-
-    /**
-     * Overwrite the {@link NdefMessage} on this tag.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param msg the NDEF Message to write, must not be null
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     * @throws FormatException if the NDEF Message to write is malformed
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
-        checkConnected();
-
-        try {
-            INfcTag tagService = mTag.getTagService();
-            if (tagService == null) {
-                throw new IOException("Mock tags don't support this operation.");
-            }
-            int serviceHandle = mTag.getServiceHandle();
-            if (tagService.isNdef(serviceHandle)) {
-                int errorCode = tagService.ndefWrite(serviceHandle, msg);
-                switch (errorCode) {
-                    case ErrorCodes.SUCCESS:
-                        break;
-                    case ErrorCodes.ERROR_IO:
-                        throw new IOException();
-                    case ErrorCodes.ERROR_INVALID_PARAM:
-                        throw new FormatException();
-                    default:
-                        // Should not happen
-                        throw new IOException();
-                }
-            }
-            else {
-                throw new IOException("Tag is not ndef");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Indicates whether a tag can be made read-only with {@link #makeReadOnly()}.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return true if it is possible to make this tag read-only
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public boolean canMakeReadOnly() {
-        INfcTag tagService = mTag.getTagService();
-        if (tagService == null) {
-            return false;
-        }
-        try {
-            return tagService.canMakeReadOnly(mNdefType);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return false;
-        }
-    }
-
-    /**
-     * Make a tag read-only.
-     *
-     * <p>This sets the CC field to indicate the tag is read-only,
-     * and where possible permanently sets the lock bits to prevent
-     * any further modification of the memory.
-     * <p>This is a one-way process and cannot be reverted!
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return true on success, false if it is not possible to make this tag read-only
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public boolean makeReadOnly() throws IOException {
-        checkConnected();
-
-        try {
-            INfcTag tagService = mTag.getTagService();
-            if (tagService == null) {
-                return false;
-            }
-            if (tagService.isNdef(mTag.getServiceHandle())) {
-                int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle());
-                switch (errorCode) {
-                    case ErrorCodes.SUCCESS:
-                        return true;
-                    case ErrorCodes.ERROR_IO:
-                        throw new IOException();
-                    case ErrorCodes.ERROR_INVALID_PARAM:
-                        return false;
-                    default:
-                        // Should not happen
-                        throw new IOException();
-                }
-           }
-           else {
-               throw new IOException("Tag is not ndef");
-           }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return false;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NdefFormatable.java b/nfc/java/android/nfc/tech/NdefFormatable.java
deleted file mode 100644
index 2240fe7..0000000
--- a/nfc/java/android/nfc/tech/NdefFormatable.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.FormatException;
-import android.nfc.INfcTag;
-import android.nfc.NdefMessage;
-import android.nfc.Tag;
-import android.nfc.TagLostException;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Provide access to NDEF format operations on a {@link Tag}.
- *
- * <p>Acquire a {@link NdefFormatable} object using {@link #get}.
- *
- * <p>Android devices with NFC must only enumerate and implement this
- * class for tags for which it can format to NDEF.
- *
- * <p>Unfortunately the procedures to convert unformated tags to NDEF formatted
- * tags are not specified by NFC Forum, and are not generally well-known. So
- * there is no mandatory set of tags for which all Android devices with NFC
- * must support {@link NdefFormatable}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class NdefFormatable extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /**
-     * Get an instance of {@link NdefFormatable} for the given tag.
-     * <p>Does not cause any RF activity and does not block.
-     * <p>Returns null if {@link NdefFormatable} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag is not NDEF formatable by this Android device.
-     *
-     * @param tag an NDEF formatable tag
-     * @return NDEF formatable object
-     */
-    public static NdefFormatable get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NDEF_FORMATABLE)) return null;
-        try {
-            return new NdefFormatable(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Internal constructor, to be used by NfcAdapter
-     * @hide
-     */
-    public NdefFormatable(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NDEF_FORMATABLE);
-    }
-
-    /**
-     * Format a tag as NDEF, and write a {@link NdefMessage}.
-     *
-     * <p>This is a multi-step process, an IOException is thrown
-     * if any one step fails.
-     * <p>The card is left in a read-write state after this operation.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param firstMessage the NDEF message to write after formatting, can be null
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     * @throws FormatException if the NDEF Message to write is malformed
-     */
-    public void format(NdefMessage firstMessage) throws IOException, FormatException {
-        format(firstMessage, false);
-    }
-
-    /**
-     * Formats a tag as NDEF, write a {@link NdefMessage}, and make read-only.
-     *
-     * <p>This is a multi-step process, an IOException is thrown
-     * if any one step fails.
-     * <p>The card is left in a read-only state if this method returns successfully.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param firstMessage the NDEF message to write after formatting
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or the operation is canceled
-     * @throws FormatException if the NDEF Message to write is malformed
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void formatReadOnly(NdefMessage firstMessage) throws IOException, FormatException {
-        format(firstMessage, true);
-    }
-
-    /*package*/ void format(NdefMessage firstMessage, boolean makeReadOnly) throws IOException,
-            FormatException {
-        checkConnected();
-
-        try {
-            int serviceHandle = mTag.getServiceHandle();
-            INfcTag tagService = mTag.getTagService();
-            if (tagService == null) {
-                throw new IOException();
-            }
-            int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
-            switch (errorCode) {
-                case ErrorCodes.SUCCESS:
-                    break;
-                case ErrorCodes.ERROR_IO:
-                    throw new IOException();
-                case ErrorCodes.ERROR_INVALID_PARAM:
-                    throw new FormatException();
-                default:
-                    // Should not happen
-                    throw new IOException();
-            }
-            // Now check and see if the format worked
-            if (!tagService.isNdef(serviceHandle)) {
-                throw new IOException();
-            }
-
-            // Write a message, if one was provided
-            if (firstMessage != null) {
-                errorCode = tagService.ndefWrite(serviceHandle, firstMessage);
-                switch (errorCode) {
-                    case ErrorCodes.SUCCESS:
-                        break;
-                    case ErrorCodes.ERROR_IO:
-                        throw new IOException();
-                    case ErrorCodes.ERROR_INVALID_PARAM:
-                        throw new FormatException();
-                    default:
-                        // Should not happen
-                        throw new IOException();
-                }
-            }
-
-            // optionally make read-only
-            if (makeReadOnly) {
-                errorCode = tagService.ndefMakeReadOnly(serviceHandle);
-                switch (errorCode) {
-                    case ErrorCodes.SUCCESS:
-                        break;
-                    case ErrorCodes.ERROR_IO:
-                        throw new IOException();
-                    case ErrorCodes.ERROR_INVALID_PARAM:
-                        throw new IOException();
-                    default:
-                        // Should not happen
-                        throw new IOException();
-                }
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NfcA.java b/nfc/java/android/nfc/tech/NfcA.java
deleted file mode 100644
index 7e66483..0000000
--- a/nfc/java/android/nfc/tech/NfcA.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Provides access to NFC-A (ISO 14443-3A) properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link NfcA} object using {@link #get}.
- * <p>The primary NFC-A I/O operation is {@link #transceive}. Applications must
- * implement their own protocol stack on top of {@link #transceive}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class NfcA extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /** @hide */
-    public static final String EXTRA_SAK = "sak";
-    /** @hide */
-    public static final String EXTRA_ATQA = "atqa";
-
-    private short mSak;
-    private byte[] mAtqa;
-
-    /**
-     * Get an instance of {@link NfcA} for the given tag.
-     * <p>Returns null if {@link NfcA} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag does not support NFC-A.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NFC-A compatible tag
-     * @return NFC-A object
-     */
-    public static NfcA get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NFC_A)) return null;
-        try {
-            return new NfcA(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public NfcA(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NFC_A);
-        Bundle extras = tag.getTechExtras(TagTechnology.NFC_A);
-        mSak = extras.getShort(EXTRA_SAK);
-        mAtqa = extras.getByteArray(EXTRA_ATQA);
-    }
-
-    /**
-     * Return the ATQA/SENS_RES bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return ATQA/SENS_RES bytes
-     */
-    public byte[] getAtqa() {
-        return mAtqa;
-    }
-
-    /**
-     * Return the SAK/SEL_RES bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return SAK bytes
-     */
-    public short getSak() {
-        return mSak;
-    }
-
-    /**
-     * Send raw NFC-A commands to the tag and receive the response.
-     *
-     * <p>Applications must not append the EoD (CRC) to the payload,
-     * it will be automatically calculated.
-     * <p>Applications must only send commands that are complete bytes,
-     * for example a SENS_REQ is not possible (these are used to
-     * manage tag polling and initialization).
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or this operation is canceled
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-
-    /**
-     * Set the {@link #transceive} timeout in milliseconds.
-     *
-     * <p>The timeout only applies to {@link #transceive} on this object,
-     * and is reset to a default value when {@link #close} is called.
-     *
-     * <p>Setting a longer timeout may be useful when performing
-     * transactions that require a long processing time on the tag
-     * such as key generation.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param timeout timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void setTimeout(int timeout) {
-        try {
-            int err = mTag.getTagService().setTimeout(TagTechnology.NFC_A, timeout);
-            if (err != ErrorCodes.SUCCESS) {
-                throw new IllegalArgumentException("The supplied timeout is not valid");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Get the current {@link #transceive} timeout in milliseconds.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public int getTimeout() {
-        try {
-            return mTag.getTagService().getTimeout(TagTechnology.NFC_A);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NfcB.java b/nfc/java/android/nfc/tech/NfcB.java
deleted file mode 100644
index 3ebd47f..0000000
--- a/nfc/java/android/nfc/tech/NfcB.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import java.io.IOException;
-
-/**
- * Provides access to NFC-B (ISO 14443-3B) properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link NfcB} object using {@link #get}.
- * <p>The primary NFC-B I/O operation is {@link #transceive}. Applications must
- * implement their own protocol stack on top of {@link #transceive}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class NfcB extends BasicTagTechnology {
-    /** @hide */
-    public static final String EXTRA_APPDATA = "appdata";
-    /** @hide */
-    public static final String EXTRA_PROTINFO = "protinfo";
-
-    private byte[] mAppData;
-    private byte[] mProtInfo;
-
-    /**
-     * Get an instance of {@link NfcB} for the given tag.
-     * <p>Returns null if {@link NfcB} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag does not support NFC-B.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NFC-B compatible tag
-     * @return NFC-B object
-     */
-    public static NfcB get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NFC_B)) return null;
-        try {
-            return new NfcB(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public NfcB(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NFC_B);
-        Bundle extras = tag.getTechExtras(TagTechnology.NFC_B);
-        mAppData = extras.getByteArray(EXTRA_APPDATA);
-        mProtInfo = extras.getByteArray(EXTRA_PROTINFO);
-    }
-
-    /**
-     * Return the Application Data bytes from ATQB/SENSB_RES at tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return Application Data bytes from ATQB/SENSB_RES bytes
-     */
-    public byte[] getApplicationData() {
-        return mAppData;
-    }
-
-    /**
-     * Return the Protocol Info bytes from ATQB/SENSB_RES at tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return Protocol Info bytes from ATQB/SENSB_RES bytes
-     */
-    public byte[] getProtocolInfo() {
-        return mProtInfo;
-    }
-
-    /**
-     * Send raw NFC-B commands to the tag and receive the response.
-     *
-     * <p>Applications must not append the EoD (CRC) to the payload,
-     * it will be automatically calculated.
-     * <p>Applications must not send commands that manage the polling
-     * loop and initialization (SENSB_REQ, SLOT_MARKER etc).
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or this operation is canceled
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NfcBarcode.java b/nfc/java/android/nfc/tech/NfcBarcode.java
deleted file mode 100644
index 421ba78..0000000
--- a/nfc/java/android/nfc/tech/NfcBarcode.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-/**
- * Provides access to tags containing just a barcode.
- *
- * <p>Acquire an {@link NfcBarcode} object using {@link #get}.
- *
- */
-public final class NfcBarcode extends BasicTagTechnology {
-
-    /** Kovio Tags */
-    public static final int TYPE_KOVIO = 1;
-    public static final int TYPE_UNKNOWN = -1;
-
-    /** @hide */
-    public static final String EXTRA_BARCODE_TYPE = "barcodetype";
-
-    private int mType;
-
-    /**
-     * Get an instance of {@link NfcBarcode} for the given tag.
-     *
-     * <p>Returns null if {@link NfcBarcode} was not enumerated in {@link Tag#getTechList}.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NfcBarcode compatible tag
-     * @return NfcBarcode object
-     */
-    public static NfcBarcode get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NFC_BARCODE)) return null;
-        try {
-            return new NfcBarcode(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Internal constructor, to be used by NfcAdapter
-     * @hide
-     */
-    public NfcBarcode(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NFC_BARCODE);
-        Bundle extras = tag.getTechExtras(TagTechnology.NFC_BARCODE);
-        if (extras != null) {
-            mType = extras.getInt(EXTRA_BARCODE_TYPE);
-        } else {
-            throw new NullPointerException("NfcBarcode tech extras are null.");
-        }
-    }
-
-    /**
-     * Returns the NFC Barcode tag type.
-     *
-     * <p>Currently only one of {@link #TYPE_KOVIO} or {@link #TYPE_UNKNOWN}.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return the NFC Barcode tag type
-     */
-    public int getType() {
-        return mType;
-    }
-
-    /**
-     * Returns the barcode of an NfcBarcode tag.
-     *
-     * <p> Tags of {@link #TYPE_KOVIO} return 16 bytes:
-     *     <ul>
-     *     <p> The first byte is 0x80 ORd with a manufacturer ID, corresponding
-     *       to ISO/IEC 7816-6.
-     *     <p> The second byte describes the payload data format. Defined data
-     *       format types include the following:<ul>
-     *       <li>0x00: Reserved for manufacturer assignment</li>
-     *       <li>0x01: 96-bit URL with "http://www." prefix</li>
-     *       <li>0x02: 96-bit URL with "https://www." prefix</li>
-     *       <li>0x03: 96-bit URL with "http://" prefix</li>
-     *       <li>0x04: 96-bit URL with "https://" prefix</li>
-     *       <li>0x05: 96-bit GS1 EPC</li>
-     *       <li>0x06-0xFF: reserved</li>
-     *       </ul>
-     *     <p>The following 12 bytes are payload:<ul>
-     *       <li> In case of a URL payload, the payload is encoded in US-ASCII,
-     *            following the limitations defined in RFC3987.
-     *            {@see <a href="http://www.ietf.org/rfc/rfc3987.txt">RFC 3987</a>}</li>
-     *       <li> In case of GS1 EPC data, see <a href="http://www.gs1.org/gsmp/kc/epcglobal/tds/">
-     *            GS1 Electronic Product Code (EPC) Tag Data Standard (TDS)</a> for more details.
-     *       </li>
-     *     </ul>
-     *     <p>The last 2 bytes comprise the CRC.
-     *     </ul>
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return a byte array containing the barcode
-     * @see <a href="http://www.thinfilm.no/docs/thinfilm-nfc-barcode-datasheet.pdf">
-     *      Thinfilm NFC Barcode tag specification (previously Kovio NFC Barcode)</a>
-     * @see <a href="http://www.thinfilm.no/docs/thinfilm-nfc-barcode-data-format.pdf">
-     *      Thinfilm NFC Barcode data format (previously Kovio NFC Barcode)</a>
-     */
-    public byte[] getBarcode() {
-        switch (mType) {
-            case TYPE_KOVIO:
-                // For Kovio tags the barcode matches the ID
-                return mTag.getId();
-            default:
-                return null;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NfcF.java b/nfc/java/android/nfc/tech/NfcF.java
deleted file mode 100644
index 2ccd388..0000000
--- a/nfc/java/android/nfc/tech/NfcF.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.ErrorCodes;
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Provides access to NFC-F (JIS 6319-4) properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link NfcF} object using {@link #get}.
- * <p>The primary NFC-F I/O operation is {@link #transceive}. Applications must
- * implement their own protocol stack on top of {@link #transceive}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class NfcF extends BasicTagTechnology {
-    private static final String TAG = "NFC";
-
-    /** @hide */
-    public static final String EXTRA_SC = "systemcode";
-    /** @hide */
-    public static final String EXTRA_PMM = "pmm";
-
-    private byte[] mSystemCode = null;
-    private byte[] mManufacturer = null;
-
-    /**
-     * Get an instance of {@link NfcF} for the given tag.
-     * <p>Returns null if {@link NfcF} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag does not support NFC-F.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NFC-F compatible tag
-     * @return NFC-F object
-     */
-    public static NfcF get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NFC_F)) return null;
-        try {
-            return new NfcF(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public NfcF(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NFC_F);
-        Bundle extras = tag.getTechExtras(TagTechnology.NFC_F);
-        if (extras != null) {
-            mSystemCode = extras.getByteArray(EXTRA_SC);
-            mManufacturer = extras.getByteArray(EXTRA_PMM);
-        }
-    }
-
-    /**
-     * Return the System Code bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return System Code bytes
-     */
-    public byte[] getSystemCode() {
-      return mSystemCode;
-    }
-
-    /**
-     * Return the Manufacturer bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return Manufacturer bytes
-     */
-    public byte[] getManufacturer() {
-      return mManufacturer;
-    }
-
-    /**
-     * Send raw NFC-F commands to the tag and receive the response.
-     *
-     * <p>Applications must not prefix the SoD (preamble and sync code)
-     * and/or append the EoD (CRC) to the payload, it will be automatically calculated.
-     *
-     * <p>A typical NFC-F frame for this method looks like:
-     * <pre>
-     * LENGTH (1 byte) --- CMD (1 byte) -- IDm (8 bytes) -- PARAMS (LENGTH - 10 bytes)
-     * </pre>
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum amount of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or this operation is canceled
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-
-    /**
-     * Set the {@link #transceive} timeout in milliseconds.
-     *
-     * <p>The timeout only applies to {@link #transceive} on this object,
-     * and is reset to a default value when {@link #close} is called.
-     *
-     * <p>Setting a longer timeout may be useful when performing
-     * transactions that require a long processing time on the tag
-     * such as key generation.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param timeout timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void setTimeout(int timeout) {
-        try {
-            int err = mTag.getTagService().setTimeout(TagTechnology.NFC_F, timeout);
-            if (err != ErrorCodes.SUCCESS) {
-                throw new IllegalArgumentException("The supplied timeout is not valid");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-        }
-    }
-
-    /**
-     * Get the current {@link #transceive} timeout in milliseconds.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @return timeout value in milliseconds
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public int getTimeout() {
-        try {
-            return mTag.getTagService().getTimeout(TagTechnology.NFC_F);
-        } catch (RemoteException e) {
-            Log.e(TAG, "NFC service dead", e);
-            return 0;
-        }
-    }
-}
diff --git a/nfc/java/android/nfc/tech/NfcV.java b/nfc/java/android/nfc/tech/NfcV.java
deleted file mode 100644
index 186c63b..0000000
--- a/nfc/java/android/nfc/tech/NfcV.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.Tag;
-import android.os.Bundle;
-import android.os.RemoteException;
-
-import java.io.IOException;
-
-/**
- * Provides access to NFC-V (ISO 15693) properties and I/O operations on a {@link Tag}.
- *
- * <p>Acquire a {@link NfcV} object using {@link #get}.
- * <p>The primary NFC-V I/O operation is {@link #transceive}. Applications must
- * implement their own protocol stack on top of {@link #transceive}.
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public final class NfcV extends BasicTagTechnology {
-    /** @hide */
-    public static final String EXTRA_RESP_FLAGS = "respflags";
-
-    /** @hide */
-    public static final String EXTRA_DSFID = "dsfid";
-
-    private byte mRespFlags;
-    private byte mDsfId;
-
-    /**
-     * Get an instance of {@link NfcV} for the given tag.
-     * <p>Returns null if {@link NfcV} was not enumerated in {@link Tag#getTechList}.
-     * This indicates the tag does not support NFC-V.
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @param tag an NFC-V compatible tag
-     * @return NFC-V object
-     */
-    public static NfcV get(Tag tag) {
-        if (!tag.hasTech(TagTechnology.NFC_V)) return null;
-        try {
-            return new NfcV(tag);
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
-    /** @hide */
-    public NfcV(Tag tag) throws RemoteException {
-        super(tag, TagTechnology.NFC_V);
-        Bundle extras = tag.getTechExtras(TagTechnology.NFC_V);
-        mRespFlags = extras.getByte(EXTRA_RESP_FLAGS);
-        mDsfId = extras.getByte(EXTRA_DSFID);
-    }
-
-    /**
-     * Return the Response Flag bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return Response Flag bytes
-     */
-    public byte getResponseFlags() {
-        return mRespFlags;
-    }
-
-    /**
-     * Return the DSF ID bytes from tag discovery.
-     *
-     * <p>Does not cause any RF activity and does not block.
-     *
-     * @return DSF ID bytes
-     */
-    public byte getDsfId() {
-        return mDsfId;
-    }
-
-    /**
-     * Send raw NFC-V commands to the tag and receive the response.
-     *
-     * <p>Applications must not append the CRC to the payload,
-     * it will be automatically calculated. The application does
-     * provide FLAGS, CMD and PARAMETER bytes.
-     *
-     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum amount of bytes
-     * that can be sent with {@link #transceive}.
-     *
-     * <p>This is an I/O operation and will block until complete. It must
-     * not be called from the main application thread. A blocked call will be canceled with
-     * {@link IOException} if {@link #close} is called from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or this operation is canceled
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
-
-
-    /**
-     * Return the maximum number of bytes that can be sent with {@link #transceive}.
-     * @return the maximum number of bytes that can be sent with {@link #transceive}.
-     */
-    public int getMaxTransceiveLength() {
-        return getMaxTransceiveLengthInternal();
-    }
-}
diff --git a/nfc/java/android/nfc/tech/TagTechnology.java b/nfc/java/android/nfc/tech/TagTechnology.java
deleted file mode 100644
index 839fe42..0000000
--- a/nfc/java/android/nfc/tech/TagTechnology.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.tech;
-
-import android.nfc.Tag;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * {@link TagTechnology} is an interface to a technology in a {@link Tag}.
- * <p>
- * Obtain a {@link TagTechnology} implementation by calling the static method <code>get()</code>
- * on the implementation class.
- * <p>
- * NFC tags are based on a number of independently developed technologies and offer a
- * wide range of capabilities. The
- * {@link TagTechnology} implementations provide access to these different
- * technologies and capabilities. Some sub-classes map to technology
- * specification (for example {@link NfcA}, {@link IsoDep}, others map to
- * pseudo-technologies or capabilities (for example {@link Ndef}, {@link NdefFormatable}).
- * <p>
- * It is mandatory for all Android NFC devices to provide the following
- * {@link TagTechnology} implementations.
- * <ul>
- * <li>{@link NfcA} (also known as ISO 14443-3A)
- * <li>{@link NfcB} (also known as ISO 14443-3B)
- * <li>{@link NfcF} (also known as JIS 6319-4)
- * <li>{@link NfcV} (also known as ISO 15693)
- * <li>{@link IsoDep}
- * <li>{@link Ndef} on NFC Forum Type 1, Type 2, Type 3 or Type 4 compliant tags
- * </ul>
- * It is optional for Android NFC devices to provide the following
- * {@link TagTechnology} implementations. If it is not provided, the
- * Android device will never enumerate that class via {@link Tag#getTechList}.
- * <ul>
- * <li>{@link MifareClassic}
- * <li>{@link MifareUltralight}
- * <li>{@link NfcBarcode}
- * <li>{@link NdefFormatable} must only be enumerated on tags for which this Android device
- * is capable of formatting. Proprietary knowledge is often required to format a tag
- * to make it NDEF compatible.
- * </ul>
- * <p>
- * {@link TagTechnology} implementations provide methods that fall into two classes:
- * <em>cached getters</em> and <em>I/O operations</em>.
- * <h4>Cached getters</h4>
- * These methods (usually prefixed by <code>get</code> or <code>is</code>) return
- * properties of the tag, as determined at discovery time. These methods will never
- * block or cause RF activity, and do not require {@link #connect} to have been called.
- * They also never update, for example if a property is changed by an I/O operation with a tag
- * then the cached getter will still return the result from tag discovery time.
- * <h4>I/O operations</h4>
- * I/O operations may require RF activity, and may block. They have the following semantics.
- * <ul>
- * <li>{@link #connect} must be called before using any other I/O operation.
- * <li>{@link #close} must be called after completing I/O operations with a
- * {@link TagTechnology}, and it will cancel all other blocked I/O operations on other threads
- * (including {@link #connect} with {@link IOException}.
- * <li>Only one {@link TagTechnology} can be connected at a time. Other calls to
- * {@link #connect} will return {@link IOException}.
- * <li>I/O operations may block, and should never be called on the main application
- * thread.
- * </ul>
- *
- * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
- * require the {@link android.Manifest.permission#NFC} permission.
- */
-public interface TagTechnology extends Closeable {
-    /**
-     * This technology is an instance of {@link NfcA}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NFC_A = 1;
-
-    /**
-     * This technology is an instance of {@link NfcB}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NFC_B = 2;
-
-    /**
-     * This technology is an instance of {@link IsoDep}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int ISO_DEP = 3;
-
-    /**
-     * This technology is an instance of {@link NfcF}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NFC_F = 4;
-
-    /**
-     * This technology is an instance of {@link NfcV}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NFC_V = 5;
-
-    /**
-     * This technology is an instance of {@link Ndef}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NDEF = 6;
-
-    /**
-     * This technology is an instance of {@link NdefFormatable}.
-     * <p>Support for this technology type is mandatory.
-     * @hide
-     */
-    public static final int NDEF_FORMATABLE = 7;
-
-    /**
-     * This technology is an instance of {@link MifareClassic}.
-     * <p>Support for this technology type is optional. If a stack doesn't support this technology
-     * type tags using it must still be discovered and present the lower level radio interface
-     * technologies in use.
-     * @hide
-     */
-    public static final int MIFARE_CLASSIC = 8;
-
-    /**
-     * This technology is an instance of {@link MifareUltralight}.
-     * <p>Support for this technology type is optional. If a stack doesn't support this technology
-     * type tags using it must still be discovered and present the lower level radio interface
-     * technologies in use.
-     * @hide
-     */
-    public static final int MIFARE_ULTRALIGHT = 9;
-
-    /**
-     * This technology is an instance of {@link NfcBarcode}.
-     * <p>Support for this technology type is optional. If a stack doesn't support this technology
-     * type tags using it must still be discovered and present the lower level radio interface
-     * technologies in use.
-     * @hide
-     */
-    public static final int NFC_BARCODE = 10;
-
-    /**
-     * Get the {@link Tag} object backing this {@link TagTechnology} object.
-     * @return the {@link Tag} backing this {@link TagTechnology} object.
-     */
-    public Tag getTag();
-
-    /**
-     * Enable I/O operations to the tag from this {@link TagTechnology} object.
-     * <p>May cause RF activity and may block. Must not be called
-     * from the main application thread. A blocked call will be canceled with
-     * {@link IOException} by calling {@link #close} from another thread.
-     * <p>Only one {@link TagTechnology} object can be connected to a {@link Tag} at a time.
-     * <p>Applications must call {@link #close} when I/O operations are complete.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @see #close()
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or connect is canceled
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void connect() throws IOException;
-
-    /**
-     * Re-connect to the {@link Tag} associated with this connection. Reconnecting to a tag can be
-     * used to reset the state of the tag itself.
-     *
-     * <p>May cause RF activity and may block. Must not be called
-     * from the main application thread. A blocked call will be canceled with
-     * {@link IOException} by calling {@link #close} from another thread.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @see #connect()
-     * @see #close()
-     * @throws TagLostException if the tag leaves the field
-     * @throws IOException if there is an I/O failure, or connect is canceled
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     * @hide
-     */
-    public void reconnect() throws IOException;
-
-    /**
-     * Disable I/O operations to the tag from this {@link TagTechnology} object, and release resources.
-     * <p>Also causes all blocked I/O operations on other thread to be canceled and
-     * return with {@link IOException}.
-     *
-     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
-     *
-     * @see #connect()
-     * @throws SecurityException if the tag object is reused after the tag has left the field
-     */
-    public void close() throws IOException;
-
-    /**
-     * Helper to indicate if I/O operations should be possible.
-     *
-     * <p>Returns true if {@link #connect} has completed, and {@link #close} has not been
-     * called, and the {@link Tag} is not known to be out of range.
-     * <p>Does not cause RF activity, and does not block.
-     *
-     * @return true if I/O operations should be possible
-     */
-    public boolean isConnected();
-}
diff --git a/nfc/java/android/nfc/tech/package.html b/nfc/java/android/nfc/tech/package.html
deleted file mode 100644
index a99828f..0000000
--- a/nfc/java/android/nfc/tech/package.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<HTML>
-<BODY>
-<p>
-These classes provide access to a tag technology's features, which vary by the type
-of tag that is scanned. A scanned tag can support multiple technologies, and you can find
-out what they are by calling {@link android.nfc.Tag#getTechList getTechList()}.</p>
-
-<p>For more information on dealing with tag technologies and handling the ones that you care about, see
-<a href="{@docRoot}guide/topics/nfc/index.html#dispatch">The Tag Dispatch System</a>.
-The {@link android.nfc.tech.TagTechnology} interface provides an overview of the
-supported technologies.</p>
-</BODY>
-</HTML>
diff --git a/nfc/lint-baseline.xml b/nfc/lint-baseline.xml
deleted file mode 100644
index 67b496e..0000000
--- a/nfc/lint-baseline.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
-
-    <issue
-        id="FlaggedApi"
-        message="Method `NfcOemExtension()` is a flagged API and should be inside an `if (Flags.nfcOemExtension())` check (or annotate the surrounding method `NfcAdapter` with `@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) to transfer requirement to caller`)"
-        errorLine1="        mNfcOemExtension = new NfcOemExtension(mContext, this);"
-        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
-            line="909"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
-        errorLine1="                &amp;&amp; ((pollTechnology &amp; FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
-            line="1917"
-            column="39"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
-        errorLine1="                &amp;&amp; ((pollTechnology &amp; FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH"
-        errorLine2="                                                                ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
-            line="1917"
-            column="65"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
-        errorLine1="                || (listenTechnology &amp; FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) {"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
-            line="1918"
-            column="40"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Field `FLAG_SET_DEFAULT_TECH` is a flagged API and should be inside an `if (Flags.nfcSetDefaultDiscTech())` check (or annotate the surrounding method `setDiscoveryTechnology` with `@FlaggedApi(Flags.FLAG_NFC_SET_DEFAULT_DISC_TECH) to transfer requirement to caller`)"
-        errorLine1="                || (listenTechnology &amp; FLAG_SET_DEFAULT_TECH) == FLAG_SET_DEFAULT_TECH)) {"
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
-            line="1918"
-            column="66"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Method `onVendorNciResponse()` is a flagged API and should be inside an `if (Flags.nfcVendorCmd())` check (or annotate the surrounding method `onVendorResponseReceived` with `@FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) to transfer requirement to caller`)"
-        errorLine1="                    executor.execute(() -> callback.onVendorNciResponse(gid, oid, payload));"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcVendorNciCallbackListener.java"
-            line="88"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="FlaggedApi"
-        message="Method `onVendorNciNotification()` is a flagged API and should be inside an `if (Flags.nfcVendorCmd())` check (or annotate the surrounding method `onVendorNotificationReceived` with `@FlaggedApi(Flags.FLAG_NFC_VENDOR_CMD) to transfer requirement to caller`)"
-        errorLine1="                    executor.execute(() -> callback.onVendorNciNotification(gid, oid, payload));"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="frameworks/base/nfc/java/android/nfc/NfcVendorNciCallbackListener.java"
-            line="106"
-            column="44"/>
-    </issue>
-
-</issues>
diff --git a/nfc/tests/Android.bp b/nfc/tests/Android.bp
deleted file mode 100644
index 17fb810..0000000
--- a/nfc/tests/Android.bp
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
-    default_team: "trendy_team_fwk_nfc",
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "frameworks_base_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
-    name: "NfcManagerTests",
-    static_libs: [
-        "androidx.test.core",
-        "androidx.test.rules",
-        "androidx.test.runner",
-        "androidx.test.ext.junit",
-        "mockito-target-extended-minus-junit4",
-        "frameworks-base-testutils",
-        "truth",
-        "androidx.annotation_annotation",
-        "androidx.appcompat_appcompat",
-        "flag-junit",
-        "platform-test-annotations",
-        "testables",
-    ],
-    libs: [
-        "androidx.annotation_annotation",
-        "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
-        "framework-permission-s.stubs.module_lib",
-        "framework-permission.stubs.module_lib",
-        "android.test.base.stubs.system",
-        "android.test.mock.stubs.system",
-        "android.test.runner.stubs.system",
-        "framework-nfc.impl",
-    ],
-    jni_libs: [
-        // Required for ExtendedMockito
-        "libdexmakerjvmtiagent",
-        "libstaticjvmtiagent",
-    ],
-    srcs: [
-        "src/**/*.java",
-        ":framework-nfc-updatable-sources",
-        ":framework-nfc-non-updatable-sources",
-    ],
-    platform_apis: true,
-    certificate: "platform",
-    test_suites: [
-        "device-tests",
-        "mts-nfc",
-    ],
-    min_sdk_version: "35", // Should be 36 later.
-}
diff --git a/nfc/tests/AndroidManifest.xml b/nfc/tests/AndroidManifest.xml
deleted file mode 100644
index 9564672..0000000
--- a/nfc/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2021 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="android.nfc">
-
-    <application android:debuggable="true">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="android.nfc"
-                     android:label="NFC Manager Tests">
-    </instrumentation>
-
-</manifest>
-
diff --git a/nfc/tests/AndroidTest.xml b/nfc/tests/AndroidTest.xml
deleted file mode 100644
index 490d6f5..0000000
--- a/nfc/tests/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2021 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for NFC Manager test cases">
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-suite-tag" value="apct-instrumentation"/>
-    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="NfcManagerTests.apk" />
-    </target_preparer>
-
-    <option name="test-suite-tag" value="apct"/>
-    <option name="test-tag" value="NfcManagerTests"/>
-
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="android.nfc" />
-        <option name="hidden-api-checks" value="false"/>
-        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
-    </test>
-</configuration>
diff --git a/nfc/tests/src/android/nfc/NdefMessageTest.java b/nfc/tests/src/android/nfc/NdefMessageTest.java
deleted file mode 100644
index 9ca295d..0000000
--- a/nfc/tests/src/android/nfc/NdefMessageTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class NdefMessageTest {
-    private NdefMessage mNdefMessage;
-    private NdefRecord mNdefRecord;
-
-    @Before
-    public void setUp() {
-        mNdefRecord = NdefRecord.createUri("http://www.example.com");
-        mNdefMessage = new NdefMessage(mNdefRecord);
-    }
-
-    @After
-    public void tearDown() {
-    }
-
-    @Test
-    public void testGetRecords() {
-        NdefRecord[] records = mNdefMessage.getRecords();
-        assertThat(records).isNotNull();
-        assertThat(records).hasLength(1);
-        assertThat(records[0]).isEqualTo(mNdefRecord);
-    }
-
-    @Test
-    public void testToByteArray() throws FormatException {
-        byte[] bytes = mNdefMessage.toByteArray();
-        assertThat(bytes).isNotNull();
-        assertThat(bytes.length).isGreaterThan(0);
-        NdefMessage ndefMessage = new NdefMessage(bytes);
-        assertThat(ndefMessage).isNotNull();
-    }
-}
diff --git a/nfc/tests/src/android/nfc/NdefRecordTest.java b/nfc/tests/src/android/nfc/NdefRecordTest.java
deleted file mode 100644
index 044c674..0000000
--- a/nfc/tests/src/android/nfc/NdefRecordTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Locale;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NdefRecordTest {
-
-    @Test
-    public void testNdefRecordConstructor() throws FormatException {
-        NdefRecord applicationRecord = NdefRecord
-                .createApplicationRecord("com.android.test");
-        NdefRecord ndefRecord = new NdefRecord(applicationRecord.toByteArray());
-        assertThat(ndefRecord).isNotNull();
-        assertThat(ndefRecord.toByteArray().length).isGreaterThan(0);
-        assertThat(ndefRecord.getType()).isEqualTo("android.com:pkg".getBytes());
-        assertThat(ndefRecord.getPayload()).isEqualTo("com.android.test".getBytes());
-    }
-
-    @Test
-    public void testCreateExternal() {
-        NdefRecord ndefRecord = NdefRecord.createExternal("test",
-                "android.com:pkg", "com.android.test".getBytes());
-        assertThat(ndefRecord).isNotNull();
-        assertThat(ndefRecord.getType()).isEqualTo("test:android.com:pkg".getBytes());
-        assertThat(ndefRecord.getPayload()).isEqualTo("com.android.test".getBytes());
-    }
-
-    @Test
-    public void testCreateUri() {
-        NdefRecord ndefRecord = NdefRecord.createUri("http://www.example.com");
-        assertThat(ndefRecord).isNotNull();
-        assertThat(ndefRecord.getTnf()).isEqualTo(NdefRecord.TNF_WELL_KNOWN);
-        assertThat(ndefRecord.getType()).isEqualTo(NdefRecord.RTD_URI);
-    }
-
-    @Test
-    public void testCreateMime() {
-        NdefRecord ndefRecord = NdefRecord.createMime("text/plain", "example".getBytes());
-        assertThat(ndefRecord).isNotNull();
-        assertThat(ndefRecord.getTnf()).isEqualTo(NdefRecord.TNF_MIME_MEDIA);
-    }
-
-    @Test
-    public void testCreateTextRecord() {
-        String languageCode = Locale.getDefault().getLanguage();
-        NdefRecord ndefRecord = NdefRecord.createTextRecord(languageCode, "testdata");
-        assertThat(ndefRecord).isNotNull();
-        assertThat(ndefRecord.getTnf()).isEqualTo(NdefRecord.TNF_WELL_KNOWN);
-        assertThat(ndefRecord.getType()).isEqualTo(NdefRecord.RTD_TEXT);
-    }
-
-}
diff --git a/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java b/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java
deleted file mode 100644
index c24816d..0000000
--- a/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NfcAntennaInfoTest {
-    private NfcAntennaInfo mNfcAntennaInfo;
-
-
-    @Before
-    public void setUp() {
-        AvailableNfcAntenna availableNfcAntenna = mock(AvailableNfcAntenna.class);
-        List<AvailableNfcAntenna> antennas = new ArrayList<>();
-        antennas.add(availableNfcAntenna);
-        mNfcAntennaInfo = new NfcAntennaInfo(1, 1, false, antennas);
-    }
-
-    @After
-    public void tearDown() {
-    }
-
-    @Test
-    public void testGetDeviceHeight() {
-        int height = mNfcAntennaInfo.getDeviceHeight();
-        assertThat(height).isEqualTo(1);
-    }
-
-    @Test
-    public void testGetDeviceWidth() {
-        int width = mNfcAntennaInfo.getDeviceWidth();
-        assertThat(width).isEqualTo(1);
-    }
-
-    @Test
-    public void testIsDeviceFoldable() {
-        boolean foldable = mNfcAntennaInfo.isDeviceFoldable();
-        assertThat(foldable).isFalse();
-    }
-
-    @Test
-    public void testGetAvailableNfcAntennas() {
-        List<AvailableNfcAntenna> antennas = mNfcAntennaInfo.getAvailableNfcAntennas();
-        assertThat(antennas).isNotNull();
-        assertThat(antennas.size()).isEqualTo(1);
-    }
-
-}
diff --git a/nfc/tests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java b/nfc/tests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java
deleted file mode 100644
index 48f4288..0000000
--- a/nfc/tests/src/android/nfc/NfcControllerAlwaysOnListenerTest.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
-import android.os.RemoteException;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Test of {@link NfcControllerAlwaysOnListener}.
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NfcControllerAlwaysOnListenerTest {
-
-    private INfcAdapter mNfcAdapter = mock(INfcAdapter.class);
-
-    private Throwable mThrowRemoteException = new RemoteException("RemoteException");
-
-    private static Executor getExecutor() {
-        return new Executor() {
-            @Override
-            public void execute(Runnable command) {
-                command.run();
-            }
-        };
-    }
-
-    private static void verifyListenerInvoked(ControllerAlwaysOnListener listener) {
-        verify(listener, times(1)).onControllerAlwaysOnChanged(anyBoolean());
-    }
-
-    @Test
-    public void testRegister_RegisterUnregisterWhenNotSupported() throws RemoteException {
-        // isControllerAlwaysOnSupported() returns false, not supported.
-        doReturn(false).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        NfcControllerAlwaysOnListener mListener =
-                new NfcControllerAlwaysOnListener(mNfcAdapter);
-        ControllerAlwaysOnListener mockListener1 = mock(ControllerAlwaysOnListener.class);
-        ControllerAlwaysOnListener mockListener2 = mock(ControllerAlwaysOnListener.class);
-
-        // Verify that the state listener will not registered with the NFC Adapter
-        mListener.register(getExecutor(), mockListener1);
-        verify(mNfcAdapter, times(0)).registerControllerAlwaysOnListener(any());
-
-        // Register a second client and no any call to NFC Adapter
-        mListener.register(getExecutor(), mockListener2);
-        verify(mNfcAdapter, times(0)).registerControllerAlwaysOnListener(any());
-
-        // Unregister first listener, and no any call to NFC Adapter
-        mListener.unregister(mockListener1);
-        verify(mNfcAdapter, times(0)).registerControllerAlwaysOnListener(any());
-        verify(mNfcAdapter, times(0)).unregisterControllerAlwaysOnListener(any());
-
-        // Unregister second listener, and no any call to NFC Adapter
-        mListener.unregister(mockListener2);
-        verify(mNfcAdapter, times(0)).registerControllerAlwaysOnListener(any());
-        verify(mNfcAdapter, times(0)).unregisterControllerAlwaysOnListener(any());
-    }
-
-    @Test
-    public void testRegister_RegisterUnregister() throws RemoteException {
-        doReturn(true).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        NfcControllerAlwaysOnListener mListener =
-                new NfcControllerAlwaysOnListener(mNfcAdapter);
-        ControllerAlwaysOnListener mockListener1 = mock(ControllerAlwaysOnListener.class);
-        ControllerAlwaysOnListener mockListener2 = mock(ControllerAlwaysOnListener.class);
-
-        // Verify that the state listener registered with the NFC Adapter
-        mListener.register(getExecutor(), mockListener1);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-
-        // Register a second client and no new call to NFC Adapter
-        mListener.register(getExecutor(), mockListener2);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-
-        // Unregister first listener
-        mListener.unregister(mockListener1);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-        verify(mNfcAdapter, times(0)).unregisterControllerAlwaysOnListener(any());
-
-        // Unregister second listener and the state listener registered with the NFC Adapter
-        mListener.unregister(mockListener2);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-        verify(mNfcAdapter, times(1)).unregisterControllerAlwaysOnListener(any());
-    }
-
-    @Test
-    public void testRegister_FirstRegisterFails() throws RemoteException {
-        doReturn(true).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        NfcControllerAlwaysOnListener mListener =
-                new NfcControllerAlwaysOnListener(mNfcAdapter);
-        ControllerAlwaysOnListener mockListener1 = mock(ControllerAlwaysOnListener.class);
-        ControllerAlwaysOnListener mockListener2 = mock(ControllerAlwaysOnListener.class);
-
-        // Throw a remote exception whenever first registering
-        doThrow(mThrowRemoteException).when(mNfcAdapter).registerControllerAlwaysOnListener(
-                any());
-
-        mListener.register(getExecutor(), mockListener1);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-
-        // No longer throw an exception, instead succeed
-        doNothing().when(mNfcAdapter).registerControllerAlwaysOnListener(any());
-
-        // Register a different listener
-        mListener.register(getExecutor(), mockListener2);
-        verify(mNfcAdapter, times(2)).registerControllerAlwaysOnListener(any());
-
-        // Ensure first and second listener were invoked
-        mListener.onControllerAlwaysOnChanged(true);
-        verifyListenerInvoked(mockListener1);
-        verifyListenerInvoked(mockListener2);
-    }
-
-    @Test
-    public void testRegister_RegisterSameListenerTwice() throws RemoteException {
-        doReturn(true).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        NfcControllerAlwaysOnListener mListener =
-                new NfcControllerAlwaysOnListener(mNfcAdapter);
-        ControllerAlwaysOnListener mockListener = mock(ControllerAlwaysOnListener.class);
-
-        // Register the same listener Twice
-        mListener.register(getExecutor(), mockListener);
-        mListener.register(getExecutor(), mockListener);
-        verify(mNfcAdapter, times(1)).registerControllerAlwaysOnListener(any());
-
-        // Invoke a state change and ensure the listener is only called once
-        mListener.onControllerAlwaysOnChanged(true);
-        verifyListenerInvoked(mockListener);
-    }
-
-    @Test
-    public void testNotify_AllListenersNotified() throws RemoteException {
-        doReturn(true).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        NfcControllerAlwaysOnListener listener = new NfcControllerAlwaysOnListener(mNfcAdapter);
-        List<ControllerAlwaysOnListener> mockListeners = new ArrayList<>();
-        for (int i = 0; i < 10; i++) {
-            ControllerAlwaysOnListener mockListener = mock(ControllerAlwaysOnListener.class);
-            listener.register(getExecutor(), mockListener);
-            mockListeners.add(mockListener);
-        }
-
-        // Invoke a state change and ensure all listeners are invoked
-        listener.onControllerAlwaysOnChanged(true);
-        for (ControllerAlwaysOnListener mListener : mockListeners) {
-            verifyListenerInvoked(mListener);
-        }
-    }
-
-    @Test
-    public void testStateChange_CorrectValue() throws RemoteException {
-        doReturn(true).when(mNfcAdapter).isControllerAlwaysOnSupported();
-        runStateChangeValue(true, true);
-        runStateChangeValue(false, false);
-
-    }
-
-    private void runStateChangeValue(boolean isEnabledIn, boolean isEnabledOut) {
-        NfcControllerAlwaysOnListener listener = new NfcControllerAlwaysOnListener(mNfcAdapter);
-        ControllerAlwaysOnListener mockListener = mock(ControllerAlwaysOnListener.class);
-        listener.register(getExecutor(), mockListener);
-        listener.onControllerAlwaysOnChanged(isEnabledIn);
-        verify(mockListener, times(1)).onControllerAlwaysOnChanged(isEnabledOut);
-        verify(mockListener, times(0)).onControllerAlwaysOnChanged(!isEnabledOut);
-    }
-}
diff --git a/nfc/tests/src/android/nfc/TechListParcelTest.java b/nfc/tests/src/android/nfc/TechListParcelTest.java
deleted file mode 100644
index a12bbbc..0000000
--- a/nfc/tests/src/android/nfc/TechListParcelTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Arrays;
-
-@RunWith(AndroidJUnit4.class)
-public class TechListParcelTest {
-
-    private static final String[] TECH_LIST_1 = new String[] { "tech1.1", "tech1.2" };
-    private static final String[] TECH_LIST_2 = new String[] { "tech2.1" };
-    private static final String[] TECH_LIST_EMPTY = new String[] {};
-
-    @Test
-    public void testWriteParcel() {
-        TechListParcel techListParcel = new TechListParcel(TECH_LIST_1, TECH_LIST_2);
-
-        Parcel parcel = Parcel.obtain();
-        techListParcel.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        TechListParcel actualTechList =
-                TechListParcel.CREATOR.createFromParcel(parcel);
-        parcel.recycle();
-
-        assertThat(actualTechList.getTechLists().length).isEqualTo(2);
-        assertThat(Arrays.equals(actualTechList.getTechLists()[0], TECH_LIST_1)).isTrue();
-        assertThat(Arrays.equals(actualTechList.getTechLists()[1], TECH_LIST_2)).isTrue();
-    }
-
-    @Test
-    public void testWriteParcelArrayEmpty() {
-        TechListParcel techListParcel = new TechListParcel();
-
-        Parcel parcel = Parcel.obtain();
-        techListParcel.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        TechListParcel actualTechList =
-                TechListParcel.CREATOR.createFromParcel(parcel);
-        parcel.recycle();
-
-        assertThat(actualTechList.getTechLists().length).isEqualTo(0);
-    }
-
-    @Test
-    public void testWriteParcelElementEmpty() {
-        TechListParcel techListParcel = new TechListParcel(TECH_LIST_EMPTY);
-
-        Parcel parcel = Parcel.obtain();
-        techListParcel.writeToParcel(parcel, 0);
-        parcel.setDataPosition(0);
-        TechListParcel actualTechList =
-                TechListParcel.CREATOR.createFromParcel(parcel);
-        parcel.recycle();
-
-        assertThat(actualTechList.getTechLists().length).isEqualTo(1);
-        assertThat(Arrays.equals(actualTechList.getTechLists()[0], TECH_LIST_EMPTY)).isTrue();
-    }
-
-}
diff --git a/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java b/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java
deleted file mode 100644
index 7e00102..0000000
--- a/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.nfc.cardemulation;
-
-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.isNull;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.os.Parcel;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class AidGroupTest {
-    private AidGroup mAidGroup;
-
-    @Before
-    public void setUp() {
-        List<String> aids = new ArrayList<>();
-        aids.add("A0000000031010");
-        aids.add("A0000000041010");
-        aids.add("A0000000034710");
-        aids.add("A000000300");
-        mAidGroup = new AidGroup(aids, "payment");
-    }
-
-    @After
-    public void tearDown() {
-    }
-
-    @Test
-    public void testGetCategory() {
-        String category = mAidGroup.getCategory();
-        assertThat(category).isNotNull();
-        assertThat(category).isEqualTo("payment");
-    }
-
-    @Test
-    public void testGetAids() {
-        List<String> aids = mAidGroup.getAids();
-        assertThat(aids).isNotNull();
-        assertThat(aids.size()).isGreaterThan(0);
-        assertThat(aids.get(0)).isEqualTo("A0000000031010");
-    }
-
-    @Test
-    public void testWriteAsXml() throws IOException {
-        XmlSerializer out = mock(XmlSerializer.class);
-        mAidGroup.writeAsXml(out);
-        verify(out, atLeastOnce()).startTag(isNull(), anyString());
-        verify(out, atLeastOnce()).attribute(isNull(), anyString(), anyString());
-        verify(out, atLeastOnce()).endTag(isNull(), anyString());
-    }
-
-    @Test
-    public void testRightToParcel() {
-        Parcel parcel = mock(Parcel.class);
-        mAidGroup.writeToParcel(parcel, 0);
-        verify(parcel).writeString8(anyString());
-        verify(parcel).writeInt(anyInt());
-        verify(parcel).writeStringList(any());
-    }
-}
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 2a8f17b..ba02bf6 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Gee &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toestemming om jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> se apps na &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&amp;gt te stroom?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sal toegang hê tot enigiets wat sigbaar is of gespeel word op <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, insluitend oudio, foto’s, wagwoorde en boodskappe.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sal apps na <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> kan stroom totdat jy toegang tot hierdie toestemming verwyder."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek namens <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps vanaf jou <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> te stroom"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Laat &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toe om oudio- en stelselkenmerke te stroom tussen jou <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> en &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sal toegang hê tot enigiets wat op jou <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> gespeel word.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sal oudio kan stroom na <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> totdat jy toegang tot hierdie toestemming verwyder."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> versoek toestemming namens <xliff:g id="DEVICE_NAME">%2$s</xliff:g> om oudio- en stelselkenmerke tussen jou toestelle te stroom."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Hierdie app sal inligting kan sinkroniseer, soos die naam van iemand wat bel, tussen jou foon en die gekose toestel"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Laat toe"</string>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index b66860e..a6b78cb 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; የእርስዎን <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> መተግበሪያዎች ወደ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;? በዥረት እንዲለቅ ይፍቀዱ"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ኦዲዮ፣ ፎቶዎች፣ የክፍያ መረጃ፣ የይለፍ ቃላት እና መልዕክቶችን ጨምሮ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ላይ የሚታየውን ወይም የሚጫወተውን የማንኛውም ነገር መዳረሻ ይኖረዋል።&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> የዚህን መዳረሻ እስኪያስወግዱ ድረስ መተግበሪያዎችን ወደ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> በዥረት መልቀቅ ይችላል።"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> መተግበሪያዎችን ከእርስዎ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> በዥረት ለመልቀቅ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ን በመወከል ፈቃድ እየጠየቀ ነው"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; የኦዲዮ እና የሥርዓት ባህሪያትን በእርስዎ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> እና &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; መካከል በዥረት እንዲለቅ ይፈቀድለት?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> በእርስዎ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ላይ ለሚጫወተው ማንኛውንም ነገር መዳረሻ ይኖረዋል።&lt;br/&gt;&lt;br/&gt;እርስዎ የዚህን ፈቃድ መዳረሻ እስኪያስወግዱ ድረስ <xliff:g id="APP_NAME_2">%1$s</xliff:g> አዲዮን ወደ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> በዥረት መልቀቅ ይችላል።"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ን በመወከል በመሣሪያዎችዎ መካከል ኦዲዮን እና የሥርዓት ባህሪያትን በዥረት ለመልቀቅ ፈቃድ እየጠየቀ ነው።"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ይህ መተግበሪያ እንደ የሚደውል ሰው ስም ያለ መረጃን በስልክዎ እና በተመረጠው መሣሪያ መካከል ማስመር ይችላል"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ፍቀድ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index 6f17676..db0704f 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -36,6 +36,12 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"هل تريد السماح لـ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ببث التطبيقات من <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> إلى <xliff:g id="DEVICE_NAME">%3$s</xliff:g>؟"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"‏سيتمكّن \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" من الوصول إلى كل المحتوى المعروض أو الذي يتم تشغيله على <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>، بما في ذلك الملفات الصوتية والصور ومعلومات الدفع وكلمات المرور والرسائل.&lt;br/&gt;&lt;br/&gt;سيتمكّن \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" من بثّ التطبيقات إلى <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> إلى أن توقِف إمكانية استخدام هذا الإذن."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"يطلب \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" الحصول على إذن نيابةً عن <xliff:g id="DEVICE_NAME">%2$s</xliff:g> لبثّ التطبيقات من <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <!-- no translation found for title_sensor_device_streaming (2395553261097861497) -->
+    <skip />
+    <!-- no translation found for summary_sensor_device_streaming (3413105061195145547) -->
+    <skip />
+    <!-- no translation found for helper_summary_sensor_device_streaming (8860174545653786353) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
     <string name="summary_generic" msgid="1761976003668044801">"سيتمكّن هذا التطبيق من مزامنة المعلومات، مثل اسم المتصل، بين هاتفك والجهاز المحدّد."</string>
     <string name="consent_yes" msgid="8344487259618762872">"السماح"</string>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index 8b001d1..c07602a 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ৰ এপ্‌সমূহ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;ত ষ্ট্ৰীম কৰিবলৈ দিবনে?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>এ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>ত দৃশ্যমান হোৱা বা প্লে’ কৰা অডিঅ’, ফট’ পাছৱৰ্ড আৰু বাৰ্তাকে ধৰি যিকোনো বস্তু এক্সেছ কৰিব পাৰিব।&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g>এ আপুনি এই অনুমতিৰ এক্সেছ আঁতৰাই নিদিয়া পৰ্যন্ত <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>ত এপ্‌সমূহ ষ্ট্ৰীম কৰিব পাৰিব।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ হৈ আপোনাৰ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ৰ পৰা এপ্‌সমূহ ষ্ট্ৰীম কৰিবলৈ অনুমতি বিচাৰি অনুৰোধ জনাইছে"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ক আপোনাৰ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> আৰু &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;ৰ মাজত অডিঅ’ আৰু ছিষ্টেমৰ সুবিধাসমূহ ষ্ট্ৰীম কৰিবলৈ দিবনে?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"আপোনাৰ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>ত প্লে’ কৰা হোৱা আটাইবোৰ সমল <xliff:g id="APP_NAME_0">%1$s</xliff:g>এ এক্সেছ কৰিব পাৰিব।&lt;br/&gt;&lt;br/&gt;আপুনি এই অনুমতিটোৰ এক্সেছ আঁতৰাই নেপেলোৱালৈকে <xliff:g id="APP_NAME_2">%1$s</xliff:g>এ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>ত অডিঅ’ ষ্ট্ৰীম কৰিব পাৰিব।"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ আপোনাৰ ডিভাইচসমূহৰ মাজত অডিঅ’ আৰু ছিষ্টেমৰ সুবিধাসমূহ ষ্ট্ৰীম কৰিবলৈ <xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ হৈ অনুমতি বিচাৰি অনুৰোধ জনাইছে।"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"এই এপ্‌টোৱে আপোনাৰ ফ’ন আৰু বাছনি কৰা ডিভাইচটোৰ মাজত কল কৰোঁতাৰ নামৰ দৰে তথ্য ছিংক কৰিব পাৰিব"</string>
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিয়ক"</string>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index b4fdcec..f053aa8 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazının tətbiqlərini &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; cihazına yayımlamaq üçün &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinə icazə verilsin?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> audio, foto, ödəniş məlumatı, parol və mesajlar daxil olmaqla <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> cihazında görünən və ya oxudulan kontentə giriş əldə edəcək.&lt;br/&gt;&lt;br/&gt;Siz bu icazəyə girişi silənə qədər <xliff:g id="APP_NAME_2">%1$s</xliff:g> tətbiqləri <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cihazında yayımlaya biləcək."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g> cihazından tətbiqləri yayımlamaq üçün <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adından icazə tələb edir"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tətbiqinin audio və sistem funksiyalarını <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> və &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;? cihazınız arasında yayımlamağına icazə verin"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> cihazınızda oxudulan istənilən kontentə daxil ola biləcək.&lt;br/&gt;&lt;br/&gt;Siz bu icazəyə girişi silənə qədər <xliff:g id="APP_NAME_2">%1$s</xliff:g> tətbiqi <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cihazına audio yayımlaya biləcək."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqi audio və sistem funksiyalarını cihazlarınız arasında yayımlamaq üçün <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adından icazə tələb edir."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Tətbiq zəng edənin adı kimi məlumatları telefon ilə seçilmiş cihaz arasında sinxronlaşdıracaq"</string>
     <string name="consent_yes" msgid="8344487259618762872">"İcazə verin"</string>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index ef97da9..621ea21 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Želite da dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; strimuje aplikacije uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što se vidi ili pušta na uređaju <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, uključujući zvuk, slike, informacije o plaćanju, lozinke i poruke.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> će moći da strimuje aplikacije na <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup ovoj dozvoli."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> traži dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da strimuje aplikacije sa uređaja <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Želite da dozvolite da &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; strimuje zvuk i sistemske funkcije između uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> i &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što se pušta na uređaju <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> će moći da strimuje zvuk na <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup ovoj dozvoli."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> traži dozvolu u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da strimuje zvuk i sistemske funkcije između uređaja."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći da sinhronizuje podatke, poput imena osobe koja upućuje poziv, između telefona i odabranog uređaja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index c0aaac9..0cdebcd 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Дазволіць праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; трансліраваць праграмы прылады тыпу \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" на прыладу &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будзе мець доступ да ўсяго, што паказваецца ці прайграецца на прыладзе \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\", у тым ліку да аўдыя, фота, плацежнай інфармацыі, пароляў і паведамленняў.&lt;br/&gt;&lt;br/&gt;Праграма \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" зможа трансліраваць праграмы на прыладу \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", пакуль вы не адклічаце гэты дазвол."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" запытвае дазвол ад імя прылады \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" на трансляцыю праграм з прылады тыпу \"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\""</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Дазволіць праграме &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; трансліраваць аўдыя і сістэмныя функцыі паміж прыладамі \"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\" і &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> будзе мець доступ да ўсяго, што прайграецца на прыладзе \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\".&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> зможа трансліраваць аўдыя на прыладу \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", пакуль вы не адклічаце гэты дазвол."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> запытвае дазвол ад імя прылады \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" на трансляцыю аўдыя і сістэмных функцый паміж прыладамі."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Гэта праграма зможа сінхранізаваць інфармацыю (напрыклад, імя таго, хто звоніць) паміж тэлефонам і выбранай прыладай"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дазволіць"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 0fa98ef..f522ab4 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Да се разреши ли на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да предава поточно към &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; приложенията на устройството ви от тип <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ще има достъп до всичко, което се показва или възпроизвежда на устройството ви <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, включително аудио, снимки, пароли и съобщения.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ще може да предава поточно приложения към устройството ви <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, докато не премахнете това разрешение."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да предава поточно приложения от устройството ви от тип <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Да се разреши ли на &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да предава поточно аудио и системни функции между устройството ви <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> и &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ще има достъп до всичко, което се възпроизвежда на устройството ви <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ще може да предава поточно аудио на устройството ви <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, докато не премахнете това разрешение."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> иска разрешение от името на <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да предава поточно аудио и системни функции между устройствата ви."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Това приложение ще може да синхронизира различна информация, като например името на обаждащия се, между телефона ви и избраното устройство"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Разрешаване"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 032eedb..61ec8c9 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-এর অ্যাপ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?-এ স্ট্রিম করার জন্য &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-কে অনুমতি দেবেন?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"অডিও, ফটো, পাসওয়ার্ড ও মেসেজ সহ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-এ দেখা ও চালানো যায় এমন সব কিছু <xliff:g id="APP_NAME_0">%1$s</xliff:g> অ্যাক্সেস করতে পারবে।&lt;br/&gt;&lt;br/&gt;আপনি এই অনুমতি না সরানো পর্যন্ত <xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-এ অ্যাপ স্ট্রিম করতে পারবে।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"আপনার <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> থেকে অ্যাপ স্ট্রিম করার জন্য <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-কে অনুমতি দিন যাতে আপনার <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ও &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?-এর মধ্যে অডিও ও সিস্টেমের ফিচার স্ট্রিম করতে পারে"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"আপনার <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-এ চালানো যায় এমন সব কিছু <xliff:g id="APP_NAME_0">%1$s</xliff:g> অ্যাক্সেস করতে পারবে। &lt;br/&gt;&lt;br/&gt;আপনি এই অনুমতি সম্পর্কিত অ্যাক্সেস সরিয়ে না দেওয়া পর্যন্ত<xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-এ অডিও স্ট্রিম করতে পারবে।"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"আপনার বিভিন্ন ডিভাইসের মধ্যে অডিও ও সিস্টেমের ফিচার স্ট্রিম করার জন্য, <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-এর হয়ে <xliff:g id="APP_NAME">%1$s</xliff:g> অনুমতি চাইছে।"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
     <string name="summary_generic" msgid="1761976003668044801">"এই অ্যাপ, আপনার ফোন এবং বেছে নেওয়া ডিভাইসের মধ্যে তথ্য সিঙ্ক করতে পারবে, যেমন কোনও কলারের নাম"</string>
     <string name="consent_yes" msgid="8344487259618762872">"অনুমতি দিন"</string>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index 183bdc8..00205f2 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Dozvoliti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da prenosi aplikacije koje sadržava vaš <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaju &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> reproducira ili je vidljivo na njemu, uključujući zvukove, fotografije, podatke o plaćanju, lozinke i poruke.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> će moći prenositi aplikacije na uređaju <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup ovom odobrenju."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> traži odobrenje u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da prenosi aplikacije s uređaja vrste \"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>\""</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Dozvoliti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da prenosi zvuk i funkcije sistema između uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> i &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> će imati pristup svemu što se reproducira na uređaju <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> će moći prenositi zvuk na uređaju <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup ovom odobrenju."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> traži odobrenje u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> da prenosi zvuk i funkcije sistema između uređaja."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ova aplikacija će moći sinhronizirati informacije, kao što je ime osobe koja upućuje poziv, između vašeg telefona i odabranog uređaja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dozvoli"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 0dc7001..662e297a 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vols permetre que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; reprodueixi en continu les aplicacions del dispositiu (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> podrà accedir a qualsevol cosa que sigui visible o que es reprodueixi al dispositiu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inclosos àudios, fotos, informació de pagament, contrasenyes i missatges.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrà reproduir en continu aplicacions al dispositiu <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> fins que suprimeixis l\'accés a aquest permís."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del dispositiu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per reproduir en continu aplicacions del teu dispositiu (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>)"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Vols permetre que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; reprodueixi en continu àudio i funcions del sistema entre el dispositiu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> i &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> podrà accedir a qualsevol cosa que es reprodueixi al teu dispositiu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrà reproduir en continu àudio al dispositiu <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> fins que suprimeixis l\'accés a aquest permís."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> demana permís en nom del dispositiu <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per reproduir en continu àudio i funcions del sistema entre els teus dispositius."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aquesta aplicació podrà sincronitzar informació, com ara el nom d\'algú que truca, entre el teu telèfon i el dispositiu triat"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permet"</string>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index b08081b..6b110d3 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Povolit aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovat aplikace na zařízení typu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zařízení &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mít přístup ke všemu, co na zařízení typu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> zobrazíte nebo přehrajete, včetně zvuku, fotek, platebních údajů, hesel a zpráv.&lt;br/&gt;&lt;br/&gt;Aplikace <xliff:g id="APP_NAME_2">%1$s</xliff:g> bude moct streamovat aplikace do zařízení typu <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dokud přístup k tomuto oprávnění neodeberete."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> žádá jménem zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o oprávnění streamovat aplikace z vašeho zařízení typu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Povolit aplikaci &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovat zvuk a systémové funkce mezi zařízeními <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mít přístup ke všemu, co se na zařízení <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> bude přehrávat.&lt;br/&gt;&lt;br/&gt;Aplikace <xliff:g id="APP_NAME_2">%1$s</xliff:g> bude moct streamovat zvuk do zařízení typu <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dokud přístup k tomuto oprávnění neodeberete."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> požaduje za vaše zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g> oprávnění ke streamování zvuku a systémových funkcí mezi vašimi zařízeními."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Tato aplikace bude moci synchronizovat údaje, jako je jméno volajícího, mezi vaším telefonem a vybraným zařízením"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Povolit"</string>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index da3b261..bbd0110 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vil du give &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilladelse til at streame apps fra din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får adgang til alt, der er synligt eller afspilles på <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, herunder lyd, billeder, betalingsoplysninger, adgangskoder og beskeder.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan streame apps til <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, indtil du fjerner adgangen til denne tilladelse."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at streame apps fra din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Vil du give &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; tilladelse til at streame lyd og systemfunktioner mellem <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> og &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får adgang til alt, der afspilles på din <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan streame lyd til <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, indtil du fjerner adgangen til denne tilladelse."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> anmoder om tilladelse på vegne af <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til at streame lyd og systemfunktioner mellem dine enheder."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Denne app vil kunne synkronisere oplysninger som f.eks. navnet på en person, der ringer, mellem din telefon og den valgte enhed"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillad"</string>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index c39145e..3eecfe7 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, die Apps auf deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) auf &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; zu streamen?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> hat dann Zugriff auf alle Inhalte, die auf deinem Gerät (<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>) sichtbar sind oder abgespielt werden, einschließlich Audioinhalten, Fotos, Zahlungsinformationen, Passwörtern und Nachrichten.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kann so lange Apps auf „<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>“ streamen, bis du diese Berechtigung entfernst."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> bittet für dein Gerät <xliff:g id="DEVICE_NAME">%2$s</xliff:g> um die Berechtigung, Apps von deinem Gerät (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>) zu streamen"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Der App &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; erlauben, Audio und Systemfunktionen zwischen deinem Gerät (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) und &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; zu streamen?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Die App „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ hat dann Zugriff auf alle Inhalte, die auf deinem Gerät (<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>) abgespielt werden.&lt;br/&gt;&lt;br/&gt;Die App „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ kann so lange Audioinhalte auf „<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>“ streamen, bis du diese Berechtigung entfernst."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Die App „<xliff:g id="APP_NAME">%1$s</xliff:g>“ bittet für das Gerät (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) um die Berechtigung, Audio und Systemfunktionen zwischen deinen Geräten zu streamen."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Diese App kann dann Daten wie den Namen eines Anrufers zwischen deinem Smartphone und dem ausgewählten Gerät synchronisieren"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Zulassen"</string>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index e465a38..a26162f 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Να επιτρέπεται στο &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; η δυνατότητα ροής εφαρμογών του <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> σας στο &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;;"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Το <xliff:g id="APP_NAME_0">%1$s</xliff:g> θα έχει πρόσβαση σε οτιδήποτε είναι ορατό ή αναπαράγεται στο <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, συμπεριλαμβανομένων ήχων, φωτογραφιών, στοιχείων πληρωμής, κωδικών πρόσβασης και μηνυμάτων.&lt;br/&gt;&lt;br/&gt;Το <xliff:g id="APP_NAME_2">%1$s</xliff:g> θα έχει τη δυνατότητα ροής εφαρμογών στο <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, μέχρι να καταργήσετε την πρόσβαση σε αυτή την άδεια."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Το <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους του <xliff:g id="DEVICE_NAME">%2$s</xliff:g> για τη ροή εφαρμογών από το <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> σας"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Να επιτρέπεται στην εφαρμογή &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; η μετάδοση σε ροή ήχου και λειτουργιών συστήματος μεταξύ της συσκευής <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> και της συσκευής &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;;"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> θα έχει πρόσβαση σε οτιδήποτε αναπαράγεται στη συσκευή <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;Η εφαρμογή <xliff:g id="APP_NAME_2">%1$s</xliff:g> θα έχει τη δυνατότητα μετάδοσης σε ροή ήχου στη συσκευή <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, μέχρι να καταργήσετε την πρόσβαση σε αυτή την άδεια."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> ζητά άδεια εκ μέρους της συσκευής <xliff:g id="DEVICE_NAME">%2$s</xliff:g> για τη μετάδοση σε ροή ήχου και λειτουργιών συστήματος μεταξύ των συσκευών σας."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Αυτή η εφαρμογή θα μπορεί να συγχρονίζει πληροφορίες μεταξύ του τηλεφώνου και της επιλεγμένης συσκευής σας, όπως το όνομα ενός ατόμου που σας καλεί."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Να επιτρέπεται"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index 92f0a1b..b5fea9f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords and messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream audio and system features between your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> and &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s played on your <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream audio to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream audio and system features between your devices."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index c40018f..42c6b88 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>’s apps to &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords, and messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream audio and system features between your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> and &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that’s played on your <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream audio to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream audio and system features between your devices."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index 92f0a1b..b5fea9f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords and messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream audio and system features between your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> and &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s played on your <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream audio to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream audio and system features between your devices."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index 92f0a1b..b5fea9f 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>\'s apps to &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s visible or played on <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, including audio, photos, payment info, passwords and messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream apps to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream apps from your <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Allow &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; to stream audio and system features between your <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> and &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> will have access to anything that\'s played on your <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> will be able to stream audio to <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> until you remove access to this permission."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> is requesting permission on behalf of <xliff:g id="DEVICE_NAME">%2$s</xliff:g> to stream audio and system features between your devices."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic" msgid="1761976003668044801">"This app will be able to sync info, like the name of someone calling, between your phone and the chosen device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Allow"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index a7a4086..a5d00a3 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"¿Quieres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; transmita las apps de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo el contenido visible o que se reproduzca en <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, lo que incluye audio, fotos, información de pago, contraseñas y mensajes.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrá transmitir apps a <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hasta que se quite el acceso a este permiso."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para transmitir apps desde tu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"¿Quieres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; transmita audio y funciones del sistema entre tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> y &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo el contenido que se reproduzca en tu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrá transmitir audio a <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hasta que se quite el acceso a este permiso."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para transmitir audio y funciones del sistema entre dispositivos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta app podrá sincronizar información, como el nombre de la persona que llama, entre el teléfono y el dispositivo elegido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index 8816e6d..fc6e6c5 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"¿Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; emita las aplicaciones de tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> en &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo lo que se vea o se reproduzca en <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, incluidos audio, fotos, información para pagos, contraseñas y mensajes.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrá emitir aplicaciones en <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hasta que quites el acceso a este permiso."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para emitir aplicaciones desde tu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"¿Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; emita audio y funciones del sistema entre tu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> y tu &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tendrá acceso a todo lo que se reproduzca en tu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> podrá emitir audio en <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hasta que quites el acceso a este permiso."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> está pidiendo permiso en nombre de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para emitir audio y funciones del sistema en otros dispositivos tuyos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación podrá sincronizar información (por ejemplo, el nombre de la persona que te llama) entre tu teléfono y el dispositivo que elijas"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index 8099537..2cbb441 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Kas lubada rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; teie seadme &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; rakendusi seadmesse <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> voogesitada?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saab juurdepääsu kõigele, mida teie seadmes <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> saab kuvada või esitada, sh helile, fotodele, makseteabele, paroolidele ja sõnumitele.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> saab rakendusi seadmesse <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> voogesitada seni, kuni juurdepääsu sellele loale eemaldate."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba rakenduste voogesitamiseks teie seadmest <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Kas lubada rakendusel &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; teie seadmete <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ja &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; vahel heli ja süsteemifunktsioone edastada?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Rakendus <xliff:g id="APP_NAME_0">%1$s</xliff:g> saab juurdepääsu kõigele, mida teie seadmes <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> esitatakse.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> saab edastada heli seadmesse <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, kuni selle loa eemaldate."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> taotleb teie seadme <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nimel luba teie seadmete vahel heli ja süsteemifunktsioonide edastamiseks."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
     <string name="summary_generic" msgid="1761976003668044801">"See rakendus saab sünkroonida teavet, näiteks helistaja nime, teie telefoni ja valitud seadme vahel"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Luba"</string>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index dd9b47c..3a49cf9 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari zure <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> gailuko aplikazioak <xliff:g id="DEVICE_NAME">%3$s</xliff:g> gailura zuzenean igortzeko baimena eman nahi diozu?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> gailuan ikusgai dagoen edo erreproduzitzen den eduki guztia atzitu ahal izango du, audioa, argazkiak, ordainketa-informazioa, pasahitzak eta mezuak barne.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> gailura aplikazioak zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="DEVICE_TYPE">%3$s</xliff:g> gailutik aplikazioak zuzenean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Zure <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> eta &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; gailuen artean audioa eta sistemaren eginbideak zuzenean igortzeko baimena eman nahi diozu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; aplikazioari?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aplikazioak <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> gailuan erreproduzitzen den eduki guztia atzitu ahal izango du.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> gailura audioa zuzenean igortzeko gai izango da, baimen hori kentzen diozun arte."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Gailuen artean audioa eta sistemaren eginbideak zuzenean igortzeko baimena eskatzen ari da <xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuaren izenean."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Telefonoaren eta hautatutako gailuaren artean informazioa sinkronizatzeko gai izango da aplikazioa (esate baterako, deitzaileen izenak)"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Eman baimena"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 7b013bf..4815225 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه می‌دهید برنامه‌های <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> را در &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; جاری‌سازی کند؟"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"‏‫<xliff:g id="APP_NAME_0">%1$s</xliff:g> به هرچیزی که در <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> شما نمایان است یا پخش می‌شود، ازجمله صداها، عکس‌ها، اطلاعات پرداخت، گذرواژه‌ها، و پیام‌ها دسترسی خواهد داشت.&lt;br/&gt;&lt;br/&gt;تا زمانی‌که دسترسی به این اجازه را حذف نکنید، <xliff:g id="APP_NAME_2">%1$s</xliff:g> می‌تواند برنامه‌ها را در <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> جاری‌سازی کند."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"‫<xliff:g id="APP_NAME">%1$s</xliff:g> ازطرف <xliff:g id="DEVICE_NAME">%2$s</xliff:g> اجازه می‌خواهد برنامه‌ها را از <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> شما جاری‌سازی کند"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"‏به &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; اجازه می‌دهید صدا و ویژگی‌های سیستم را بین <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> و &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; جاری‌سازی کند؟"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"‏‫«<xliff:g id="APP_NAME_0">%1$s</xliff:g>» به هرچیزی که در <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> پخش می‌شود دسترسی خواهد داشت.&lt;br/&gt;&lt;br/&gt;تا زمانی‌که دسترسی به این اجازه را حذف نکنید، <xliff:g id="APP_NAME_2">%1$s</xliff:g> می‌تواند صدا در <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> جاری‌سازی کند."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"‫«<xliff:g id="APP_NAME">%1$s</xliff:g>» ازطرف <xliff:g id="DEVICE_NAME">%2$s</xliff:g> اجازه می‌خواهد صدا و ویژگی‌های سیستم را بین دستگاه‌های شما جاری‌سازی کند."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
     <string name="summary_generic" msgid="1761976003668044801">"این برنامه مجاز می‌شود اطلاعتی مثل نام شخصی را که تماس می‌گیرد بین تلفن شما و دستگاه انتخاب‌شده همگام‌سازی کند"</string>
     <string name="consent_yes" msgid="8344487259618762872">"اجازه دادن"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index f20b71b..6e13d6c 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Saako &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; striimata <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> olevia sovelluksia laitteelle (&lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;)?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saa pääsyn kaikkeen <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> näkyvään tai pelattavaan sisältöön, mukaan lukien audioon, kuviin, salasanoihin ja viesteihin.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> voi striimata sovelluksia laitteelle (<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>), kunnes poistat luvan."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää lapsen (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa striimata sovelluksia laitteeltasi (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>)"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Saako &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; striimata audiota ja järjestelmän ominaisuuksia laitteiden <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ja &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; välillä?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> saa pääsyn kaikkeen, mitä <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> toistaa.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> voi striimata audiota laitteelle (<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>), kunnes poistat luvan."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> pyytää laitteen (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) puolesta lupaa striimata audiota ja järjestelmän ominaisuuksia laitteiden välillä."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Sovellus voi synkronoida tietoja (esimerkiksi soittajan nimen) puhelimesi ja valitun laitteen välillä"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Salli"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index c4a8447..73a180b 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à diffuser les applis de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> vers &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, y compris le contenu audio, les photos, les infos de paiement, les mots de passe et les messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> pourra diffuser des applis vers <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> jusqu\'à ce que vous retiriez l\'accès à cette autorisation."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de votre <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de diffuser des applis à partir de votre <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à diffuser des fonctionnalités audio et système entre votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> et votre &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est lu sur votre <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> pourra diffuser de l\'audio sur le <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> jusqu\'à ce que vous retiriez l\'accès à cette autorisation."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation au nom de <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de diffuser des fonctionnalités audio et système entre vos appareils."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Cette appli pourra synchroniser des informations, comme le nom de l\'appelant, entre votre téléphone et l\'appareil sélectionné"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index 88627e5..0c0ae79 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à caster les applis de votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> sur &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est visible ou lu sur votre <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, y compris les contenus audio, les photos, les infos de paiement, les mots de passe et les messages.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> pourra caster des applis sur <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> jusqu\'à ce que vous supprimiez l\'accès à cette autorisation."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande, au nom de l\'appareil <xliff:g id="DEVICE_NAME">%2$s</xliff:g>, l\'autorisation de caster des applis depuis votre <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Autoriser &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; à caster des applis et des fonctionnalités système entre votre <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> et &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> aura accès à tout ce qui est lu sur votre <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> pourra caster des contenus audio sur <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> jusqu\'à ce que vous supprimiez cette autorisation."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> demande l\'autorisation pour <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de caster des fonctionnalités audio et système d\'un appareil à l\'autre."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Cette appli pourra synchroniser des infos, comme le nom de l\'appelant, entre votre téléphone et l\'appareil choisi"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Autoriser"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index a2bd0f8..71eb86ff 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Queres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; emita as aplicacións do dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) en &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acceso a todo o que se vexa ou reproduza no teu dispositivo (<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>), como audio, fotos, información de pago, contrasinais e mensaxes.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá emitir aplicacións en <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ata que quites o acceso a este permiso."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> está solicitando permiso en nome dun dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para emitir aplicacións do seguinte aparello: <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Queres permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; emita audio e funcións do sistema entre o teu dispositivo (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) e outro aparello &lt;strong&gt;(<xliff:g id="DEVICE_NAME">%3$s</xliff:g>)&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acceso a todo o que se vexa ou reproduza no dispositivo (<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>).&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá emitir audio no dispositivo (<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>) ata que quites o acceso a este permiso."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicita permiso en nome dun dispositivo (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>) para emitir audio e funcións do sistema entre os teus aparellos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta aplicación poderá sincronizar información (por exemplo, o nome de quen chama) entre o teléfono e o dispositivo escollido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index c18ebc0..9b20886 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"શું &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ની ઍપને &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; પર સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>ની પાસે એવી બધી બાબતોનો ઍક્સેસ રહેશે જે <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> પર જોઈ શકાતી કે ચલાવી શકાતી હોય, જેમાં ઑડિયો, ફોટા, ચુકવણીની માહિતી, પાસવર્ડ અને મેસેજ શામેલ છે.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ત્યાં સુધી ઍપને <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> પર સ્ટ્રીમ કરી શકશે, જ્યાં સુધી તમે આ પરવાનગીનો ઍક્સેસ કાઢી નહીં નાખો."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> તમારા <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>માંથી ઍપ સ્ટ્રીમ કરવા માટે <xliff:g id="DEVICE_NAME">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;ને તમારા <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> અને &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; વચ્ચે ઑડિયો અને સિસ્ટમની સુવિધાઓ સ્ટ્રીમ કરવાની મંજૂરી આપીએ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"તમારા <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> પર જે કંઈપણ ચલાવવામાં આવે, તેનો ઍક્સેસ <xliff:g id="APP_NAME_0">%1$s</xliff:g> પાસે રહેશે.&lt;br/&gt;&lt;br/&gt;જ્યાં સુધી તમે આ પરવાનગીનો ઍક્સેસ કાઢો નહીં, ત્યાં સુધી <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> પર ઑડિયો સ્ટ્રીમ કરી શકશે."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"તમારા ડિવાઇસ વચ્ચે ઑડિયો અને સિસ્ટમની અન્ય સુવિધાઓ સ્ટ્રીમ કરવા માટે, <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> વતી પરવાનગીની વિનંતી કરી રહી છે."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"આ ઍપ તમારા ફોન અને પસંદ કરેલા ડિવાઇસ વચ્ચે, કૉલ કરનાર કોઈ વ્યક્તિનું નામ જેવી માહિતી સિંક કરી શકશે"</string>
     <string name="consent_yes" msgid="8344487259618762872">"મંજૂરી આપો"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 562f762..f4a95a4 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -36,6 +36,12 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"क्या &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; को आपके <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> में मौजूद ऐप्लिकेशन को &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; पर स्ट्रीम करने की अनुमति देनी है?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> के पास ऐसे किसी भी कॉन्टेंट का ऐक्सेस होगा जो आपके <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> पर दिखता है या चलाया जाता है. इसमें ऑडियो, फ़ोटो, पेमेंट संबंधी जानकारी, पासवर्ड, और मैसेज शामिल हैं.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> पर तब ऐप्लिकेशन को स्ट्रीम कर सकेगा, जब तक आप यह अनुमति हटा न दें."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> को <xliff:g id="DEVICE_NAME">%2$s</xliff:g> की ओर से, आपके <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> में मौजूद ऐप्लिकेशन को स्ट्रीम करने की अनुमति चाहिए"</string>
+    <!-- no translation found for title_sensor_device_streaming (2395553261097861497) -->
+    <skip />
+    <!-- no translation found for summary_sensor_device_streaming (3413105061195145547) -->
+    <skip />
+    <!-- no translation found for helper_summary_sensor_device_streaming (8860174545653786353) -->
+    <skip />
     <string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
     <string name="summary_generic" msgid="1761976003668044801">"यह ऐप्लिकेशन, आपके फ़ोन और चुने हुए डिवाइस के बीच जानकारी सिंक करेगा. जैसे, कॉल करने वाले व्यक्ति का नाम"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दें"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index 17b4538..0b769f0 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Želite li dopustiti aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; da streama aplikacije uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na uređaj &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> imat će pristup svemu što je vidljivo ili se reproducira na uređaju <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, uključujući zvuk, fotografije, podatke o plaćanju, zaporke i poruke.&lt;br/&gt;&lt;br/&gt;Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> moći će streamati aplikacije na uređaj <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup za to dopuštenje."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za streaming aplikacija s vašeg uređaja <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Želite li aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dopustiti streaming zvuka i značajki sustava između uređaja <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> i &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> imat će pristup svemu što se reproducira na vašem uređaju <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> moći će streamati zvuk na uređaj <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> dok ne uklonite pristup za to dopuštenje."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> zahtijeva dopuštenje u ime uređaja <xliff:g id="DEVICE_NAME">%2$s</xliff:g> za streaming zvuka i značajki sustava između vaših uređaja."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta će aplikacija moći sinkronizirati podatke između vašeg telefona i odabranog uređaja, primjerice ime pozivatelja"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dopusti"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index 4b0dd49..69bd41b 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Engedélyezi a(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; számára a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> alkalmazásainak streamelését a következőre: &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> hozzáférhet a(z) <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> minden látható vagy lejátszható tartalmához, így az audiotartalmakhoz, fényképekhez, fizetési adatokhoz, jelszavakhoz és üzenetekhez is.&lt;br/&gt;&lt;br/&gt;Amíg Ön el nem távolítja az ehhez az engedélyhez való hozzáférést, a(z) <xliff:g id="APP_NAME_2">%1$s</xliff:g> képes lesz majd az alkalmazások <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> eszközre való streamelésére."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében az alkalmazások következőről való streameléséhez: <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Engedélyezi a(z) &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; számára a hang- és rendszerfunkciók streamelését a(z) <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> és a(z) &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; között?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"A(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> hozzáférhet majd mindenhez, ami a(z) <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> eszközön lejátszásra kerül.&lt;br/&gt;&lt;br/&gt;Amíg Ön el nem távolítja az ehhez az engedélyhez való hozzáférést, a(z) <xliff:g id="APP_NAME_2">%1$s</xliff:g> képes lesz majd audiotartalmakat streamelni a(z)<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> eszközre."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> engedélyt kér a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nevében az audio- és rendszerfunkcióknak az Ön eszközei közötti streameléséhez."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ez az alkalmazás képes lesz szinkronizálni az olyan információkat a telefon és a kiválasztott eszköz között, mint például a hívó fél neve."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Engedélyezés"</string>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index 744168b..27cd975 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին հեռարձակել ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ի հավելվածները &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; սարքին։"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածին հասանելի կլինի ձեր <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-ում ցուցադրվող կամ նվագարկվող բովանդակությունը՝ ներառյալ աուդիոն, լուսանկարները, վճարային տեղեկությունները, գաղտնաբառերը և հաղորդագրությունները։&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> հավելվածը կկարողանա հավելվածներ հեռարձակել <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> սարքին, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը <xliff:g id="DEVICE_NAME">%2$s</xliff:g> սարքի անունից թույլտվություն է խնդրում՝ ձեր <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ից հավելվածներ հեռարձակելու համար"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Թույլատրե՞լ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; հավելվածին աուդիո և համակարգի գործառույթներ հեռարձակել ձեր <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ի և &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;-ի միջև"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածին հասանելի կլինի ձեր <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-ում նվագարկվող բովանդակությունը։&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> հավելվածը կկարողանա աուդիո հեռարձակել <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-ին, քանի դեռ չեք չեղարկել այս թույլտվությունը։"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ի անունից թույլտվություն է խնդրում՝ ձեր սարքերի միջև աուդիո և համակարգի գործառույթներ հեռարձակելու համար։"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Այս հավելվածը կկարողանա համաժամացնել ձեր հեռախոսի և ընտրված սարքի տվյալները, օր․՝ զանգողի անունը"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Թույլատրել"</string>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index 86e8918..6ec3392 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan streaming aplikasi <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ke &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan memiliki akses ke apa pun yang ditampilkan atau diputar di <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, termasuk audio, foto, info pembayaran, sandi, dan pesan.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> akan dapat melakukan streaming aplikasi ke <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hingga Anda menghapus izin ini."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta izin atas nama <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk melakukan streaming aplikasi dari <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> Anda"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Izinkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; melakukan streaming audio dan fitur sistem antara <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> dan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan memiliki akses ke apa pun yang diputar di <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> Anda.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> akan dapat melakukan streaming audio ke <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hingga Anda menghapus akses ke izin ini."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> meminta izin untuk melakukan streaming audio dan fitur sistem antar-perangkat Anda."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aplikasi ini akan dapat menyinkronkan info, seperti nama penelepon, antara ponsel dan perangkat yang dipilih"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Izinkan"</string>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index 7294e16..f1b6ced 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Leyfa &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; að streyma forritum <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> í &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> fær aðgang að öllu sem er sýnilegt eða spilað í <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, þ.m.t. hljóði, myndum, greiðsluupplýsingum, aðgangsorðum og skilaboðum.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> getur streymt forritum í <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> þar til þú fjarlægir þessa heimild."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir hönd <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til að streyma forritum úr <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Leyfa &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; að streyma hljóði og kerfiseiginleikum á milli <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> og &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> fær aðgang að öllu sem þú spilar í <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> mun geta streymt hljóði í <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> þar til þú afturkallar heimildina."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> biður um heimild fyrir hönd <xliff:g id="DEVICE_NAME">%2$s</xliff:g> til að streyma hljóði og kerfiseiginleikum á milli tækjanna þinna."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Þetta forrit mun geta samstillt upplýsingar, t.d. nafn þess sem hringir, á milli símans og valins tækis"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Leyfa"</string>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index fe4cc15..2afdcba 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Consentire all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di riprodurre in streaming le app <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> su &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> avrà accesso a tutti i contenuti visibili o riprodotti dal tuo <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inclusi audio, foto, dati di pagamento, password e messaggi.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sarà in grado di riprodurre in streaming le app su <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> finché non rimuoverai l\'accesso a questa autorizzazione."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede l\'autorizzazione per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per riprodurre in streaming le app dal tuo <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Consentire all\'app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; di riprodurre in streaming funzionalità di sistema e audio tra <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> e &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> avrà accesso a tutto ciò che viene riprodotto sul tuo <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sarà in grado di riprodurre in streaming l\'audio su <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> finché non rimuoverai l\'accesso a questa autorizzazione."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> richiede l\'autorizzazione per conto di <xliff:g id="DEVICE_NAME">%2$s</xliff:g> per riprodurre in streaming funzionalità di sistema e audio tra i tuoi dispositivi."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Questa app potrà sincronizzare informazioni, ad esempio il nome di un chiamante, tra il telefono e il dispositivo scelto"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Consenti"</string>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index 1600031..4181e62 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"‏לאשר לאפליקציית &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לשדר את האפליקציות של ה<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ל-&lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"‏לאפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> תהיה גישה לכל מה שרואים או מפעילים ב-<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, כולל אודיו, תמונות, פרטי תשלום, סיסמאות והודעות.&lt;br/&gt;&lt;br/&gt;לאפליקציה <xliff:g id="APP_NAME_2">%1$s</xliff:g> תהיה אפשרות לשדר אפליקציות ל-<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> עד שהגישה להרשאה הזו תוסר."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת הרשאה ל-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> כדי לשדר אפליקציות מה<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"‏לאשר לאפליקציה &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; לשדר תכונות מערכת ואודיו בין ה<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> שלך לבין &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"‏לאפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> תהיה גישה לכל מה שיופעל במכשיר <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;האפליקציה <xliff:g id="APP_NAME_2">%1$s</xliff:g> תוכל לשדר אודיו אל <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> עד שההרשאה הזו תוסר."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מבקשת בשם <xliff:g id="DEVICE_NAME">%2$s</xliff:g> הרשאה כדי לשדר תכונות מערכת ואודיו בין המכשירים שלך."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
     <string name="summary_generic" msgid="1761976003668044801">"האפליקציה הזו תוכל לסנכרן מידע, כמו השם של מישהו שמתקשר, מהטלפון שלך למכשיר שבחרת"</string>
     <string name="consent_yes" msgid="8344487259618762872">"יש אישור"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 639e8bc..5974c6b 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> のアプリを &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; にストリーミングすることを &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に許可しますか?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、音声、写真、お支払い情報、パスワード、メッセージを含め、<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> で表示、再生されるすべてのコンテンツにアクセスできるようになります。&lt;br/&gt;&lt;br/&gt;この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_2">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> にアプリをストリーミングできます。"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって、アプリを <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> からストリーミングする権限をリクエストしています"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> と &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; との間で音声やシステム機能をストリーミングすることを &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; に許可しますか?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> は、<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> で再生されるすべてのコンテンツにアクセスできるようになります。&lt;br/&gt;&lt;br/&gt;この権限へのアクセス権を削除するまで、<xliff:g id="APP_NAME_2">%1$s</xliff:g> は <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> に音声をストリーミングできます。"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> が <xliff:g id="DEVICE_NAME">%2$s</xliff:g> に代わって、デバイス間で音声やシステム機能をストリーミングする権限をリクエストしています。"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
     <string name="summary_generic" msgid="1761976003668044801">"このアプリは、あなたのスマートフォンと選択したデバイスとの間で、通話相手の名前などの情報を同期できるようになります"</string>
     <string name="consent_yes" msgid="8344487259618762872">"許可"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 949d64b..de1c8e1 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"გსურთ, &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-ს მისცეთ თქვენი <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-ის აპების სტრიმინგის საშუალება &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;-ზე?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> მიიღებს წვდომას ყველაფერზე, რაც ჩანს ან უკრავს <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-ზე, მათ შორის, აუდიოზე, ფოტოებზე, პაროლებსა და შეტყობინებებზე.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> შეძლებს აპების სტრიმინგს <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-ზე მანამ, სანამ თქვენ არ გააუქმებთ წვდომას ამ ნებართვაზე."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის სახელით აპების სტრიმინგისთვის თქვენი <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-იდან"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"გსურთ, ნება დართოთ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-ს აუდიოს და სისტემის ფუნქციების სტრიმინგზე თქვენს <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-სა და &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;-ს შორის?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> მიიღებს წვდომას ყველაფერზე, რაც უკრავს თქვენს <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>-ზე.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> შეძლებს აუდიოს სტრიმინგს <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-ზე, სანამ თქვენ გააუქმებთ წვდომას ამ ნებართვაზე."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ითხოვს ნებართვას <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის სახელით, რათა მოახდინოს აუდიოს და სისტემის სხვა ფუნქციების სტრიმინგი თქვენს მოწყობილობებს შორის."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ეს აპი შეძლებს ინფორმაციის სინქრონიზებას თქვენს ტელეფონსა და თქვენ მიერ არჩეულ მოწყობილობას შორის, მაგალითად, იმ ადამიანის სახელის, რომელიც გირეკავთ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"დაშვება"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 8351542..27492a0 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына құрылғыңыздағы (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) қолданбаларды &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; құрылғысына трансляциялауға рұқсат берілсін бе?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы құрылғыда (<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>) көрінетін не ойнатылатын барлық контентті, соның ішінде аудиофайлдарды, фотосуреттерді, төлем туралы ақпаратты, құпия сөздер мен хабарларды пайдалана алады.&lt;br/&gt;&lt;br/&gt;Осы рұқсатты өшірмесеңіз, <xliff:g id="APP_NAME_2">%1$s</xliff:g> қолданбасы құрылғыға (<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>) қолданбаларды трансляциялай алады."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME">%2$s</xliff:g> атынан құрылғыдағы (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>) қолданбаларды трансляциялауға рұқсат сұрайды."</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; қолданбасына <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> құрылғыңыз бен &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; құрылғысы арасында аудио және жүйе функцияларын трансляциялауға рұқсат берілсін бе?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> құрылғыңызда ойнатылатын барлық контентті пайдалана алады.&lt;br/&gt;&lt;br/&gt;Бұл рұқсатты өшірмесеңіз, <xliff:g id="APP_NAME_2">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> құрылғысына аудионы трансляциялай алады."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы <xliff:g id="DEVICE_NAME">%2$s</xliff:g> атынан құрылғыларыңыз арасында аудио және жүйе функцияларын трансляциялауға рұқсат сұрайды."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Бұл қолданба телефон мен таңдалған құрылғы арасында деректі (мысалы, қоңырау шалушының атын) синхрондай алады."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Рұқсат беру"</string>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index 79ec5f1..55216e5 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ផ្សាយកម្មវិធីលើ<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>របស់អ្នកទៅ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ឬ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> នឹងមានសិទ្ធិចូលប្រើអ្វីៗដែលអាចមើលឃើញ ឬត្រូវបានចាក់នៅលើ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> រួមទាំងសំឡេង រូបថត ព័ត៌មាននៃការទូទាត់ប្រាក់ ពាក្យសម្ងាត់ និងសារ។&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> នឹងអាចផ្សាយកម្មវិធីទៅ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> រហូតទាល់តែអ្នកដកសិទ្ធិចូលប្រើការអនុញ្ញាតនេះចេញ។"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ដើម្បីផ្សាយកម្មវិធីពី<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>របស់អ្នក"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"អនុញ្ញាតឱ្យ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ចាក់សំឡេង និងមុខងារប្រព័ន្ធរវាង <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> និង &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; របស់អ្នកឬ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> នឹងមានសិទ្ធិចូលប្រើអ្វីៗដែលត្រូវបានចាក់នៅលើ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> របស់អ្នក។&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> នឹងអាចចាក់សំឡេងទៅ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> រហូតទាល់តែអ្នកដកសិទ្ធិចូលប្រើការអនុញ្ញាតនេះចេញ។"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងស្នើសុំការអនុញ្ញាតជំនួសឱ្យ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ដើម្បីចាក់សំឡេង និងមុខងារប្រព័ន្ធរវាងឧបករណ៍របស់អ្នក។"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
     <string name="summary_generic" msgid="1761976003668044801">"កម្មវិធីនេះនឹងអាច​ធ្វើសមកាលកម្មព័ត៌មាន ដូចជាឈ្មោះមនុស្សដែលហៅទូរសព្ទជាដើម​ រវាងឧបករណ៍ដែលបានជ្រើសរើស និងទូរសព្ទរបស់អ្នក"</string>
     <string name="consent_yes" msgid="8344487259618762872">"អនុញ្ញាត"</string>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 7cf4069..7dcb4e3 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ನ ಆ್ಯಪ್‌ಗಳನ್ನು <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"ಆಡಿಯೋ, ಫೋಟೋಗಳು, ಪಾವತಿ ಮಾಹಿತಿ, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಸಂದೇಶಗಳು ಸೇರಿದಂತೆ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ನಲ್ಲಿ ಗೋಚರಿಸುವ ಅಥವಾ ಪ್ಲೇ ಆಗುವ ಎಲ್ಲದಕ್ಕೂ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ನೀವು ಈ ಅನುಮತಿಗೆ ಆ್ಯಕ್ಸೆಸ್‌ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ಗೆ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME_2">%1$s</xliff:g> ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ನಿಂದ ಆ್ಯಪ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಗಾಗಿ ವಿನಂತಿಸುತ್ತಿದೆ"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"ನಿಮ್ಮ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ಮತ್ತು <xliff:g id="DEVICE_NAME">%3$s</xliff:g> ರ ನಡುವೆ ಆಡಿಯೋ ಮತ್ತು ಸಿಸ್ಟಮ್ ಫೀಚರ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸಬೇಕೆ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"ನಿಮ್ಮ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗುವ ಯಾವುದಕ್ಕೂ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ. ನೀವು ಈ ಅನುಮತಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೆಗೆದುಹಾಕುವವರೆಗೆ <xliff:g id="APP_NAME_2">%1$s</xliff:g> ಗೆ ಆಡಿಯೋಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ಸಾಧನಕ್ಕೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"ನಿಮ್ಮ ಸಾಧನಗಳ ನಡುವೆ ಆಡಿಯೋ ಮತ್ತು ಸಿಸ್ಟಮ್ ಫೀಚರ್‌ಗಳನ್ನು ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ನ ಪರವಾಗಿ <xliff:g id="APP_NAME">%1$s</xliff:g> ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸುತ್ತಿದೆ."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ಮೊಬೈಲ್ ಫೋನ್ ಮತ್ತು ಆಯ್ಕೆಮಾಡಿದ ಸಾಧನದ ನಡುವೆ, ಕರೆ ಮಾಡುವವರ ಹೆಸರಿನಂತಹ ಮಾಹಿತಿಯನ್ನು ಸಿಂಕ್ ಮಾಡಲು ಈ ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ಅನುಮತಿಸಿ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index c384363..ff8ed16 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>의 앱을 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; 기기로 스트리밍하도록 허용하시겠습니까?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>에서 오디오, 사진, 결제 정보, 비밀번호, 메시지 등 <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>에 표시되거나 해당 기기에서 재생되는 모든 항목에 액세스할 수 있습니다.&lt;br/&gt;&lt;br/&gt;이 권한에 대한 액세스를 삭제할 때까지 <xliff:g id="APP_NAME_2">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> 기기로 앱을 스트리밍할 수 있습니다."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 대신 <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>의 앱을 스트리밍할 권한을 요청하고 있습니다."</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 기기와 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; 기기 간에 오디오 및 시스템 기능을 스트리밍하도록 허용하시겠습니까?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> 앱이 <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>에서 재생되는 모든 항목에 액세스할 수 있습니다.&lt;br/&gt;&lt;br/&gt;이 권한에 대한 액세스를 삭제할 때까지 <xliff:g id="APP_NAME_2">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> 기기로 오디오를 스트리밍할 수 있습니다."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 대신 기기 간에 오디오 및 시스템 기능을 스트리밍할 권한을 요청하고 있습니다."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
     <string name="summary_generic" msgid="1761976003668044801">"이 앱에서 휴대전화와 선택한 기기 간에 정보(예: 발신자 이름)를 동기화할 수 있게 됩니다."</string>
     <string name="consent_yes" msgid="8344487259618762872">"허용"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 70bdf1f..8c39dd2 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> түзмөгүңүздөгү колдонмолорду &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; түзмөгүнө алып ойнотууга уруксат бересизби?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> түзмөгүңүздө көрүнгөн же ойнотулган бардык нерселерге, анын ичинде аудио, сүрөттөр, төлөм маалыматы, сырсөздөр жана билдирүүлөргө кире алат.&lt;br/&gt;&lt;br/&gt;Бул уруксатты алып салмайынча, <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> түзмөгүндөгү колдонмолорду алып ойното алат."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> түзмөгүңүздөн колдонмолорду алып ойнотуу үчүн <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүнүн атынан уруксат сурап жатат"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; колдонмосуна <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> жана &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; түзмөктөрүнүн ортосунда аудиону жана тутумдун башка функцияларын алып ойнотууга уруксат бересизби?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> түзмөгүндө ойнотулган бардык нерселерге мүмкүнчүлүк ала алат.&lt;br/&gt;&lt;br/&gt;Бул уруксатты алып салмайынча, <xliff:g id="APP_NAME_2">%1$s</xliff:g> аудиону <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> түзмөгүнө алып ойното алат."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> түзмөгүңүздүн атынан түзмөктөрдүн ортосунда аудиону жана тутумдун башка функцияларын алып ойнотууга уруксат сурап жатат."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Бул колдонмо маалыматты шайкештире алат, мисалы, чалып жаткан кишинин атын телефон жана тандалган түзмөк менен шайкештирет"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ооба"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index f8da499..a7cc51e 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ອະນຸຍາດໃຫ້ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ສະຕຣີມແອັບຂອງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານໄປຫາ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ບໍ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ປາກົດ ຫຼື ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, ເຊິ່ງຮວມທັງສຽງ, ຮູບພາບ, ຂໍ້ມູນການຈ່າຍເງິນ, ລະຫັດຜ່ານ ແລະ ຂໍ້ຄວາມ.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ຈະສາມາດສະຕຣີມແອັບໄປຫາ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ເພື່ອສະຕຣີມແອັບຈາກ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ຂອງທ່ານ"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"ອະນຸຍາດໃຫ້ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ສະຕຣີມສຽງ ແລະ ຄຸນສົມບັດຂອງລະບົບລະຫວ່າງ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ຂອງທ່ານກັບ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ບໍ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ຈະມີສິດເຂົ້າເຖິງທຸກຢ່າງທີ່ຫຼິ້ນຢູ່ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ຂອງທ່ານ.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ຈະສາມາດສະຕຣີມສຽງໄປຫາ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ໄດ້ຈົນກວ່າທ່ານຈະລຶບສິດເຂົ້າເຖິງການອະນຸຍາດນີ້ອອກ."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງຮ້ອງຂໍການອະນຸຍາດໃນນາມຂອງ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ເພື່ອສະຕຣີມສຽງ ແລະ ຄຸນສົມບັດຂອງລະບົບລະຫວ່າງອຸປະກອນຕ່າງໆຂອງທ່ານ."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ແອັບນີ້ຈະສາມາດຊິ້ງຂໍ້ມູນ ເຊັ່ນ: ຊື່ຂອງຄົນທີ່ໂທເຂົ້າ, ລະຫວ່າງໂທລະສັບຂອງທ່ານ ແລະ ອຸປະກອນທີ່ເລືອກໄວ້ໄດ້"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ອະນຸຍາດ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 7a5f347..b537508 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Leisti programai &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; srautu perduoti <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> programas į &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ galės pasiekti visą „<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>“ matomą ar leidžiamą turinį, įskaitant garso įrašus, nuotraukas, mokėjimo informaciją, slaptažodžius ir pranešimus.&lt;br/&gt;&lt;br/&gt;Programa „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ galės perduoti srautu programas į „<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>“, kol pašalinsite prieigą prie šio leidimo."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti programas iš jūsų <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Leisti programai &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; srautu perduoti garsą ir sistemos funkcijas iš <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> į &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“ galės pasiekti visą jūsų „<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>“ leidžiamą turinį.&lt;br/&gt;&lt;br/&amp;gtPrograma „<xliff:g id="APP_NAME_2">%1$s</xliff:g>“ galės srautu perduoti garsą į „<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>“, kol pašalinsite prieigą prie šio leidimo."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ prašo leidimo „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“ vardu, kad galėtų srautu perduoti garsą ir sistemos funkcijas iš vieno įrenginio į kitą."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ši programa galės sinchronizuoti tam tikrą informaciją, pvz., skambinančio asmens vardą, su jūsų telefonu ir pasirinktu įrenginiu"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Leisti"</string>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index 2d79d53..e310fe2 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vai atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; straumēt <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> lietotnes ierīcē &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> varēs piekļūt visam <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ekrānā parādītajam vai atskaņotajam saturam, tostarp audio, fotoattēliem, maksājumu informācijai, parolēm un ziņojumiem.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> varēs straumēt lietotnes ierīcē <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, līdz noņemsiet piekļuvi šai atļaujai."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju <xliff:g id="DEVICE_NAME">%2$s</xliff:g> vārdā straumēt lietotnes no jūsu ierīces <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>."</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Vai atļaut lietotnei &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; straumēt audio un sistēmas funkcijas starp jūsu ierīci <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> un ierīci &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Lietotne <xliff:g id="APP_NAME_0">%1$s</xliff:g> varēs piekļūt visam jūsu ierīces <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> atskaņotajam saturam.&lt;br/&gt;&lt;br/&gt;Lietotne <xliff:g id="APP_NAME_2">%1$s</xliff:g> varēs straumēt audio ierīcē <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, līdz noņemsiet piekļuvi šai atļaujai."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> pieprasa atļauju straumēt audio un sistēmas funkcijas starp jūsu ierīcēm šīs ierīces vārdā: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Šī lietotne varēs sinhronizēt informāciju (piemēram, zvanītāja vārdu) starp jūsu tālruni un izvēlēto ierīci"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Atļaut"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index a69a12e..08b422b 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Да се дозволи &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да ги стримува апликациите од <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ќе има пристап до сè што е видливо или репродуцирано на <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, вклучувајќи ги и аудиото, фотографиите, податоците за плаќање, лозинките и пораките.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ќе може да стримува апликации на <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> сѐ додека не ја отстраните дозволава."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на <xliff:g id="DEVICE_NAME">%2$s</xliff:g> за да стримува апликации од вашиот <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Да се дозволи &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; да стримува аудио и системски функции меѓу вашиот <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> и &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ќе има пристап до сè што е пуштено на вашиот <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ќе може да стримува аудио на <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> сѐ додека не ја отстраните дозволава."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> бара дозвола во име на <xliff:g id="DEVICE_NAME">%2$s</xliff:g> за да стримува аудио и системски функции меѓу вашите уреди."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Оваа апликација ќе може да ги синхронизира податоците како што се имињата на јавувачите помеѓу вашиот телефон и избраниот уред"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index 1a19f22..ab9671e 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> എന്നതിന്റെ ആപ്പുകൾ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; എന്നതിലേക്ക് സ്ട്രീം ചെയ്യാൻ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"ഓഡിയോ, ഫോട്ടോകൾ, പേയ്മെന്റ് വിവരങ്ങൾ, പാസ്‌വേഡുകൾ, സന്ദേശങ്ങൾ എന്നിവ ഉൾപ്പെടെ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> എന്നതിൽ ദൃശ്യമാകുന്നതോ പ്ലേ ചെയ്യുന്നതോ എല്ലാ എല്ലാത്തിലേക്കും <xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്നതിന് ആക്സസ് ഉണ്ടായിരിക്കും.&lt;br/&gt;&lt;br/&gt;നിങ്ങൾ ഈ അനുമതിയിലേക്കുള്ള ആക്സസ് നീക്കം ചെയ്യുന്നത് വരെ <xliff:g id="APP_NAME_2">%1$s</xliff:g> എന്നതിന് <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> എന്നതിലേക്ക് ആപ്പുകൾ സ്ട്രീം ചെയ്യാനാകും."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> എന്നതിൽ നിന്ന് ആപ്പുകൾ സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്നതിന്റെ പേരിൽ <xliff:g id="APP_NAME">%1$s</xliff:g> അനുമതി അഭ്യർത്ഥിക്കുന്നു"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; എന്നതിനെ നിങ്ങളുടെ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; എന്നിവ തമ്മിൽ ഓഡിയോയും സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാൻ അനുവദിക്കണോ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> എന്നതിൽ പ്ലേ ചെയ്യുന്ന എല്ലാത്തിലേക്കും <xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്നതിന് ആക്സസ് ഉണ്ടായിരിക്കും.&lt;br/&gt;&lt;br/&gt;നിങ്ങൾ ഈ അനുമതിയിലേക്കുള്ള ആക്സസ് നീക്കം ചെയ്യുന്നത് വരെ <xliff:g id="APP_NAME_2">%1$s</xliff:g> എന്നതിന് <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> എന്നതിലേക്ക് ഓഡിയോ സ്ട്രീം ചെയ്യാനാകും."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"നിങ്ങളുടെ ഉപകരണങ്ങളിൽ ഒന്നിൽ നിന്ന് അടുത്തതിലേക്ക് ഓഡിയോയും സിസ്റ്റം ഫീച്ചറുകളും സ്ട്രീം ചെയ്യാൻ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്ന ഉപകരണത്തിന് വേണ്ടി <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നത് അനുമതി അഭ്യർത്ഥിക്കുന്നു."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
     <string name="summary_generic" msgid="1761976003668044801">"വിളിക്കുന്നയാളുടെ പേര് പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ ഫോണിനും തിരഞ്ഞെടുത്ത ഉപകരണത്തിനും ഇടയിൽ സമന്വയിപ്പിക്കുന്നതിന് ഈ ആപ്പിന് കഴിയും"</string>
     <string name="consent_yes" msgid="8344487259618762872">"അനുവദിക്കുക"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index 96951ad..7b0a08a 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д таны <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>-н аппыг &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;-д дамжуулахыг зөвшөөрөх үү?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> аудио, зураг, төлбөрийн мэдээлэл, нууц үг, мессеж зэрэг <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> дээр харагдаж, тоглуулж буй аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> таныг энэ зөвшөөрөлд хандах эрхийг нь хасах хүртэл <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-д апп дамжуулах боломжтой байх болно."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс таны <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>-с апп дамжуулах зөвшөөрлийг хүсэж байна"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;-д <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;-н хооронд аудио, системийн онцлогуудыг дамжуулахыг зөвшөөрөх үү?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> таны <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> дээр тоглуулж буй аливаа зүйлд хандах эрхтэй болно.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> таныг энэ зөвшөөрлийг хасах хүртэл <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>-д аудио дамжуулах боломжтой байх болно."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g>-н өмнөөс таны төхөөрөмжүүдийн хооронд аудио, системийн онцлогуудыг дамжуулах зөвшөөрлийг хүсэж байна."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Энэ апп залгаж буй хүний нэр зэрэг мэдээллийг таны утас болон сонгосон төхөөрөмжийн хооронд синк хийх боломжтой болно"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Зөвшөөрөх"</string>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 9520a32..e18f86e 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ला अ‍ॅप्स &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;वर स्ट्रीम करण्याची अनुमती द्यायची आहे का?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ला ऑडिओ, फोटो, पेमेंट माहिती, पासवर्ड आणि मेसेज यांसह तुमच्या <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> वर दिसणाऱ्या किंवा प्ले होणाऱ्या सर्व गोष्टींचा अ‍ॅक्सेस असेल.&lt;br/&gt;&lt;br/&gt;तुम्ही या परवानगीचा अ‍ॅक्सेस काढून टाकेपर्यंत <xliff:g id="APP_NAME_2">%1$s</xliff:g> हे <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> वर ॲप्स स्ट्रीम करू शकेल."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> वरून अ‍ॅप्स आणि सिस्टीम वैशिष्ट्ये स्ट्रीम करण्यासाठी <xliff:g id="DEVICE_NAME">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ला तुमच्या <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> आणि &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; दरम्यान ऑडिओ आणि सिस्टीम वैशिष्ट्ये स्ट्रीम करू द्यायची आहेत का?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ला तुमच्या <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> वर प्ले केलेल्या कोणत्याही गोष्टीचा अ‍ॅक्सेस असेल.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> हे तुम्ही या परवानगीचा अ‍ॅक्सेस काढून टाकेपर्यंत <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> वर ऑडिओ स्ट्रीम करू शकेल."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे तुमच्या डिव्हाइसदरम्यान ऑडिओ आणि सिस्टीम वैशिष्ट्ये स्ट्रीम करण्यासाठी <xliff:g id="DEVICE_NAME">%2$s</xliff:g> च्या वतीने परवानगीची विनंती करत आहे."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
     <string name="summary_generic" msgid="1761976003668044801">"हे ॲप तुमचा फोन आणि निवडलेल्या डिव्‍हाइसदरम्यान कॉल करत असलेल्‍या एखाद्या व्यक्तीचे नाव यासारखी माहिती सिंक करू शकेल"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमती द्या"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index b3c8bd0..31cb3b7 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; untuk menstrim apl <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda kepada &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua kandungan yang dipaparkan atau dimainkan pada <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, termasuk audio, foto, maklumat pembayaran, kata laluan dan mesej.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> akan dapat menstrim apl kepada <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstrim apl daripada <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> anda"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Benarkan &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; menstrim audio dan ciri sistem antara <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> anda dengan &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> akan mendapat akses kepada semua kandungan yang dimainkan pada <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> anda.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> akan dapat menstrim audio kepada <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> sehingga anda mengalih keluar akses kepada kebenaran ini."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> meminta kebenaran bagi pihak <xliff:g id="DEVICE_NAME">%2$s</xliff:g> untuk menstrim audio dan ciri sistem antara peranti anda."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Apl ini akan dapat menyegerakkan maklumat seperti nama individu yang memanggil, antara telefon anda dengan peranti yang dipilih"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Benarkan"</string>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index bb4e7c5..0b0273f 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; အား သင့် <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ၏ အက်ပ်များကို &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; တွင် တိုက်ရိုက်ဖွင့်ခွင့်ပြုမလား။"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> သည် အသံ၊ ဓာတ်ပုံ၊ စကားဝှက်နှင့် မက်ဆေ့ဂျ်များအပါအဝင် <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> တွင် မြင်နိုင်သော (သို့) ဖွင့်ထားသော အရာအားလုံးကို သုံးခွင့်ရှိပါမည်။&lt;br/&gt;&lt;br/&gt;ဤခွင့်ပြုချက်သုံးခွင့်ကို သင်မဖယ်ရှားမချင်း <xliff:g id="APP_NAME_2">%1$s</xliff:g> သည် <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> တွင် အက်ပ်များကို တိုက်ရိုက်ဖွင့်နိုင်ပါမည်။"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့် <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> မှ အက်ပ်များကို တိုက်ရိုက်ဖွင့်ရန် <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"သင်၏ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> နှင့် &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; အကြား အသံနှင့် စနစ်အင်္ဂါရပ်များ တိုက်ရိုက်ဖွင့်ရန် &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ကို ခွင့်ပြုမလား။"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> သည် သင်၏ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> တွင် ဖွင့်ထားသော မည်သည့်အရာကိုမဆို သုံးခွင့်ရှိပါမည်။&lt;br/&gt;&lt;br/&gt;ဤခွင့်ပြုချက်သုံးခွင့်ကို သင်မဖယ်ရှားမချင်း <xliff:g id="APP_NAME_2">%1$s</xliff:g> သည် <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> တွင် အသံ တိုက်ရိုက်ဖွင့်နိုင်ပါမည်။"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် သင့်စက်များအကြား အသံနှင့် စနစ်အင်္ဂါရပ်များ တိုက်ရိုက်ဖွင့်ရန် <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ကိုယ်စား ခွင့်ပြုချက်တောင်းနေသည်။"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ဤအက်ပ်သည် သင့်ဖုန်းနှင့် ရွေးထားသောစက်အကြား ခေါ်ဆိုသူ၏အမည်ကဲ့သို့ အချက်အလက်ကို စင့်ခ်လုပ်နိုင်ပါမည်"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ခွင့်ပြုရန်"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index e8adbcd..ccb2c57 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vil du la &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; strømme apper fra <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> til &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> kan se som vises eller spilles av på <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inkludert lyd, bilder, passord og meldinger.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan strømme apper til <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> frem til du fjerner tilgangen til denne tillatelsen."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme apper fra <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> på vegne av <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Vil du la &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; strømme lyd og systemfunksjoner mellom <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> og &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får tilgang til alt som spilles av på <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan strømme lyd til <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> frem til du fjerner denne tillatelsen."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ber om tillatelse til å strømme lyd og systemfunksjoner mellom enhetene dine på vegne av <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Denne appen kan synkronisere informasjon som navnet til noen som ringer, mellom telefonen og den valgte enheten"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillat"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index 6386057..203eaee 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> मा भएका एपहरू &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; मा स्ट्रिम गर्न दिने हो?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ले <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> मा देखिने वा प्ले गरिने अडियो, फोटो, भुक्तानीसम्बन्धी जानकारी, पासवर्ड र म्यासेजलगायतका सबै कुरा एक्सेस गर्न सक्ने छ।&lt;br/&gt;&lt;br/&gt;तपाईंले यो अनुमति रद्द नगरेसम्म <xliff:g id="APP_NAME_2">%1$s</xliff:g> ले एपहरू <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> मा स्ट्रिम गर्न पाइराख्ने छ।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> को तर्फबाट तपाईंको <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> बाट एपहरू स्ट्रिम गर्ने अनुमति माग्दै छ"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; लाई तपाईंको <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> र &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; का बिचमा अडियो र सिस्टमका सुविधाहरू स्ट्रिम गर्ने अनुमति दिने हो?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ले तपाईंको <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> मा प्ले गरिने सबै कुरा एक्सेस गर्न सक्ने छ।&lt;br/&gt;&lt;br/&gt;तपाईंले यो अनुमति रद्द नगरेसम्म <xliff:g id="APP_NAME_2">%1$s</xliff:g> ले <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> मा अडियो स्ट्रिम गर्न पाइराख्ने छ।"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले डिभाइस <xliff:g id="DEVICE_NAME">%2$s</xliff:g> को तर्फबाट तपाईंका डिभाइसहरूका बिचमा अडियो र सिस्टमका सुविधाहरू स्ट्रिम गर्ने अनुमति माग्दै छ।"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
     <string name="summary_generic" msgid="1761976003668044801">"यो एपले तपाईंको फोन र तपाईंले छनौट गर्ने डिभाइसका बिचमा कल गर्ने व्यक्तिको नाम जस्ता जानकारी सिंक गर्न सक्ने छ।"</string>
     <string name="consent_yes" msgid="8344487259618762872">"अनुमति दिनुहोस्"</string>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 58c7d4f..069c00c 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toestaan om apps van je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> naar &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; te streamen?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krijgt toegang tot alles wat zichtbaar is of wordt afgespeeld op <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, waaronder audio, foto\'s, wachtwoorden en berichten.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan apps naar <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> streamen totdat je dit recht verwijdert."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om apps te streamen vanaf je <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; toestaan om audio en systeemfuncties te streamen tussen je <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> en &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krijgt toegang tot alles wat wordt afgespeeld op je <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan audio naar <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> streamen totdat je de toegang tot dit recht intrekt."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> vraagt namens <xliff:g id="DEVICE_NAME">%2$s</xliff:g> toestemming om audio en systeemfuncties te streamen tussen je apparaten."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Deze app kan informatie, zoals de naam van iemand die belt, synchroniseren tussen je telefoon en het gekozen apparaat"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Toestaan"</string>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index d431fb9..a1a6c90 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ର ଆପ୍ସକୁ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;ରେ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"ଅଡିଓ, ଫଟୋ, ପାସୱାର୍ଡ ଏବଂ ମେସେଜ ସମେତ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>ରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆକ୍ସେସ ରହିବ।&lt;br/&gt;&lt;br/&gt;ଆପଣ ଏହି ଅନୁମତିକୁ ଆକ୍ସେସ କାଢ଼ି ନଦେବା ପର୍ଯ୍ୟନ୍ତ <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>ରେ ଆପ୍ସକୁ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ ସକ୍ଷମ ହେବ।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ରୁ ଆପ୍ସ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ତରଫରୁ ଅନୁମତି ଅନୁରୋଧ କରୁଛି"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"ଆପଣଙ୍କ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ଏବଂ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ମଧ୍ୟରେ ଅଡିଓ ଏବଂ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"ଆପଣଙ୍କ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>ରେ ପ୍ଲେ ହେଉଥିବା ସବୁକିଛିକୁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆକ୍ସେସ ରହିବ।&lt;br/&gt;&lt;br/&gt;ଆପଣ ଏହି ଅନୁମତିକୁ ଆକ୍ସେସ କାଢ଼ି ନଦେବା ପର୍ଯ୍ୟନ୍ତ <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>ରେ ଅଡିଓ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="APP_NAME_2">%1$s</xliff:g> ସକ୍ଷମ ହେବ।"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"ଆପଣଙ୍କ ଡିଭାଇସଗୁଡ଼ିକ ମଧ୍ୟରେ ଅଡିଓ ଏବଂ ସିଷ୍ଟମ ଫିଚରଗୁଡ଼ିକ ଷ୍ଟ୍ରିମ କରିବା ପାଇଁ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ତରଫରୁ <xliff:g id="APP_NAME">%1$s</xliff:g> ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି।"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ଆପଣଙ୍କ ଫୋନ ଏବଂ ବଛାଯାଇଥିବା ଡିଭାଇସ ମଧ୍ୟରେ, କଲ କରୁଥିବା ଯେ କୌଣସି ବ୍ୟକ୍ତିଙ୍କ ନାମ ପରି ସୂଚନା ସିଙ୍କ କରିବାକୁ ଏହି ଆପ ସକ୍ଷମ ହେବ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 463a02b..cd40ec7 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ਕੀ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ਦੀਆਂ ਐਪਾਂ ਨੂੰ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; \'ਤੇ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਕੋਲ ਆਡੀਓ, ਫ਼ੋਟੋਆਂ, ਭੁਗਤਾਨ ਜਾਣਕਾਰੀ, ਪਾਸਵਰਡਾਂ ਅਤੇ ਸੁਨੇਹਿਆਂ ਸਮੇਤ, <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> \'ਤੇ ਦਿਖਾਈ ਦੇਣ ਵਾਲੀ ਜਾਂ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਹਟਾ ਨਹੀਂ ਦਿੰਦੇ, ਉਦੋਂ ਤੱਕ <xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> \'ਤੇ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ।"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> ਤੋਂ ਐਪਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"ਕੀ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ਨੂੰ ਆਪਣੇ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ਅਤੇ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; \'ਤੇ ਆਡੀਓ ਅਤੇ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਕੋਲ ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> \'ਤੇ ਚਲਾਈ ਜਾਣ ਵਾਲੀ ਕਿਸੇ ਵੀ ਚੀਜ਼ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ।&lt;br/&gt;&lt;br/&gt;ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਇਸ ਇਜਾਜ਼ਤ ਤੱਕ ਪਹੁੰਚ ਨੂੰ ਹਟਾ ਨਹੀਂ ਦਿੰਦੇ, ਉਦੋਂ ਤੱਕ <xliff:g id="APP_NAME_2">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> \'ਤੇ ਆਡੀਓ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰ ਸਕੇਗੀ।"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ਦੀ ਤਰਫ਼ੋਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸਾਂ ਵਿਚਕਾਰ ਆਡੀਓ ਅਤੇ ਸਿਸਟਮ ਸੰਬੰਧੀ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਸਟ੍ਰੀਮ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਰਹੀ ਹੈ।"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਅਤੇ ਚੁਣੇ ਗਏ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਕਾਲਰ ਦੇ ਨਾਮ ਵਰਗੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸਿੰਕ ਕਰ ਸਕੇਗੀ"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ਆਗਿਆ ਦਿਓ"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index dc7977d..b167766 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Zezwolić aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na strumieniowanie aplikacji na <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na urządzenie &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> będzie miała dostęp do wszystkiego, co jest widoczne i odtwarzane na <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, w tym do dźwięku, zdjęć, haseł i wiadomości.&lt;br/&gt;&lt;br/&gt;Aplikacja <xliff:g id="APP_NAME_2">%1$s</xliff:g> będzie mogła strumieniować aplikacje na urządzenie <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dopóki nie usuniesz dostępu do tego uprawnienia."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o pozwolenie na strumieniowanie aplikacji z urządzenia <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Zezwolić aplikacji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na strumieniowanie dźwięku i funkcji systemowych między urządzeniami <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> i &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> będzie miała dostęp do wszystkiego, co jest odtwarzane na urządzeniu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;Aplikacja <xliff:g id="APP_NAME_2">%1$s</xliff:g> będzie mogła strumieniować dźwięk na urządzenie <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dopóki nie usuniesz dostępu do tego uprawnienia."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> o pozwolenie na strumieniowanie dźwięku i funkcji systemowych między Twoimi urządzeniami."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacja może synchronizować informacje takie jak imię i nazwisko osoby dzwoniącej między Twoim telefonem i wybranym urządzeniem"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Zezwól"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 88cf563..a6c09d0 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming dos aplicativos do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, incluindo áudios, fotos, informações de pagamento, senhas e mensagens.&lt;br/&gt;&lt;br/&gt;O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá fazer streaming de aplicativos para o <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming de áudio e recursos do sistema entre o <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> e o &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que for aberto no seu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá fazer streaming de áudio para o <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de áudio e recursos do sistema entre seus dispositivos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 34034f0..01af6df 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Permitir que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça stream das apps do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o dispositivo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> vai ter acesso a tudo o que seja visível ou reproduzido no dispositivo <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, incluindo áudio, fotos, informações de pagamento, palavras-passe e mensagens.&lt;br/&gt;&lt;br/&gt;A app <xliff:g id="APP_NAME_2">%1$s</xliff:g> vai poder fazer stream de apps para o dispositivo <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até remover o acesso a esta autorização."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de apps do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Permitir que a app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça stream de áudio e funcionalidades do sistema entre o seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> e o &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> vai ter acesso a tudo o que for reproduzido no seu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;A app <xliff:g id="APP_NAME_2">%1$s</xliff:g> vai poder fazer stream de áudio para o <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até remover o acesso a esta autorização."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> está a pedir autorização em nome do <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer stream de áudio e funcionalidades do sistema entre os seus dispositivos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Esta app vai poder sincronizar informações, como o nome do autor de uma chamada, entre o telemóvel e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 88cf563..a6c09d0 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Permitir que o app &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming dos aplicativos do seu <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> para o &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que estiver visível ou for aberto no <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, incluindo áudios, fotos, informações de pagamento, senhas e mensagens.&lt;br/&gt;&lt;br/&gt;O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá fazer streaming de aplicativos para o <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de apps do seu <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Permitir que &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; faça streaming de áudio e recursos do sistema entre o <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> e o &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> terá acesso a tudo que for aberto no seu <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;O app <xliff:g id="APP_NAME_2">%1$s</xliff:g> poderá fazer streaming de áudio para o <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> até que você remova o acesso a essa permissão."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> está pedindo permissão em nome do <xliff:g id="DEVICE_NAME">%2$s</xliff:g> para fazer streaming de áudio e recursos do sistema entre seus dispositivos."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
     <string name="summary_generic" msgid="1761976003668044801">"O app poderá sincronizar informações, como o nome de quem está ligando, entre seu smartphone e o dispositivo escolhido"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permitir"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 002c552..2b8b5e1 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Permiți ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să redea în stream aplicații de pe <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> pe &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> va avea acces la tot conținutul vizibil sau redat pe <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inclusiv conținut audio, fotografii, informații de plată, parole și mesaje.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> va putea să redea în stream aplicații pe <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> până când elimini accesul la această permisiune."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a reda în stream aplicații de pe <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Permiți ca &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; să redea în stream conținut audio și funcții de sistem între <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> și &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> va avea acces la tot conținutul redat pe <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> va putea să redea în stream conținut audio pe <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> până când elimini accesul la această permisiune."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> solicită permisiunea pentru <xliff:g id="DEVICE_NAME">%2$s</xliff:g> de a reda în stream conținut audio și funcții de sistem între dispozitive."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Aplicația va putea să sincronizeze informații, cum ar fi numele unui apelant, între telefonul tău și dispozitivul ales"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Permite"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 6f06a2a..605fbd9 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Разрешить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать приложения с вашего устройства (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) на устройство &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"У приложения \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" будет доступ ко всему, что показывается или воспроизводится на устройстве \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\", включая аудиофайлы, фотографии, платежные данные, пароли и сообщения.&lt;br/&gt;&lt;br/&gt;Приложение \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" сможет транслировать приложения на устройство \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", пока вы не отзовете разрешение."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени вашего устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать приложения с устройства (<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>)."</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Разрешить приложению &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслировать аудио и системные функции между вашим устройством (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>) и устройством &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Приложение \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" получит доступ ко всему, что воспроизводится на устройстве \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\".&lt;br/&gt;&lt;br/&gt;Приложение \"<xliff:g id="APP_NAME_2">%1$s</xliff:g>\" сможет транслировать аудио на устройство \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", пока вы не отзовете это разрешение."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" от имени устройства \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запрашивает разрешение транслировать аудио и системные функции между устройствами."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Приложение сможет синхронизировать информацию между телефоном и выбранным устройством, например данные из журнала звонков."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Разрешить"</string>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index c4b2966..63024ca 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> හි යෙදුම් &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; වෙත ප්‍රවාහ කිරීමට &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඉඩ දෙන්න ද?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> හට ශ්‍රව්‍ය, ඡායාරූප, ගෙවීම් තොරතුරු, මුරපද සහ පණිවිඩ ඇතුළුව <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> හි දෘශ්‍යමාන හෝ වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ඇත.&lt;br/&gt;&lt;br/&gt;ඔබ මෙම අවසරයට ප්‍රවේශය ඉවත් කරන තෙක් <xliff:g id="APP_NAME_2">%1$s</xliff:g> හට <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> වෙත යෙදුම් ප්‍රවාහ කිරීමට හැකි වනු ඇත."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> වෙනුවෙන් ඔබේ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> වෙතින් යෙදුම් ප්‍රවාහ කිරීමට අවසර ඉල්ලා සිටියි"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; හට ඔබේ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> සහ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; අතර ශ්‍රව්‍ය සහ පද්ධති විශේෂාංග ප්‍රවාහ කිරීමට ඉඩ දෙන්න ද?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> හට ඔබේ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> හි වාදනය වන ඕනෑම දෙයකට ප්‍රවේශය ලැබෙනු ඇත.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> හට මෙම අවසරයට ප්‍රවේශය ඉවත් කරන තුරු <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> වෙත ශ්‍රව්‍ය ප්‍රවාහ කිරීමට හැකි වනු ඇත."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> ඔබේ උපාංග අතර ශ්‍රව්‍ය සහ පද්ධති විශේෂාංග ප්‍රවාහ කිරීමට <xliff:g id="DEVICE_NAME">%2$s</xliff:g> වෙනුවෙන් අවසර ඉල්ලා සිටී."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
     <string name="summary_generic" msgid="1761976003668044801">"මෙම යෙදුමට ඔබේ දුරකථනය සහ තෝරා ගත් උපාංගය අතර, අමතන කෙනෙකුගේ නම වැනි, තතු සමමුහුර්ත කිරීමට හැකි වනු ඇත"</string>
     <string name="consent_yes" msgid="8344487259618762872">"ඉඩ දෙන්න"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index bf96c5c..f80ceca 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať aplikácie zo zariadenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> do zariadenia &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mať prístup k všetkému, čo sa zobrazuje alebo prehráva v zariadení <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> vrátane zvuku, fotiek, platobných údajov, hesiel a správ.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> bude môcť streamovať aplikácie do zariadenia <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, kým prístup k tomuto povoleniu neodstránite."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje v mene zariadenia <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie streamovať aplikácie z vášho zariadenia <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Chcete povoliť aplikácii &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamovať zvuk a systémové funkcie medzi zariadením <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> a zariadením &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g> bude mať prístup k všetkému, čo sa prehráva v zariadení <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;Aplikácia <xliff:g id="APP_NAME_2">%1$s</xliff:g> bude môcť streamovať zvuk do zariadenia <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, kým prístup k tomuto povoleniu neodstránite."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> vyžaduje pre zariadenie <xliff:g id="DEVICE_NAME">%2$s</xliff:g> povolenie streamovať zvuk a systémové funkcie medzi vašimi zariadeniami."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Táto aplikácia bude môcť synchronizovať informácie, napríklad meno volajúceho, medzi telefónom a vybraným zariadením"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Povoliť"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index 2c1edcd..2db2b78 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Ali aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite, da pretočno predvaja aplikacije naprave <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> v napravi &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar je prikazano ali se predvaja v napravi <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, vključno z zvokom, fotografijami, podatki za plačilo, gesli in sporočili.&lt;br/&gt;&lt;br/&gt;Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> bo lahko pretočno predvajala aplikacije v napravo <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>, dokler ne odstranite dostopa do tega dovoljenja."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave <xliff:g id="DEVICE_NAME">%2$s</xliff:g> zahteva dovoljenje za pretočno predvajanje aplikacij iz naprave <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Ali aplikaciji &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; dovolite pretočno predvajanje zvoka in sistemskih funkcij med napravo »<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>« in napravo &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> bo imela dostop do vsega, kar se predvaja v napravi »<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>«.&lt;br/&gt;&lt;br/&gt;Aplikacija <xliff:g id="APP_NAME_2">%1$s</xliff:g> bo lahko pretočno predvajala zvok v napravo »<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>«, dokler ne odstranite dostopa do tega dovoljenja."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> v imenu naprave »<xliff:g id="DEVICE_NAME">%2$s</xliff:g>« zahteva dovoljenje za pretočno predvajanje zvoka in sistemskih funkcij v vaših napravah."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ta aplikacija bo lahko sinhronizirala podatke, na primer ime klicatelja, v telefonu in izbrani napravi."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Dovoli"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index 33d2430..45f008d 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Të lejohet që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të transmetojë aplikacionet nga <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> te &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> do të ketë qasje te çdo gjë që është e dukshme ose që luhet te <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, duke përfshirë audion, fotografitë, informacionet për pagesën, fjalëkalimet dhe mesazhet.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> do të mund t\'i transmetojë aplikacionet në <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> derisa ta heqësh qasjen për këtë leje."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_NAME">%2$s</xliff:g> për të transmetuar aplikacione nga <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Të lejohet që &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; të transmetojë audion dhe veçoritë e sistemit mes <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> dhe &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> do të ketë qasje në çdo gjë që luhet në pajisjen tënde <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> do të mund të transmetojë audion te <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> derisa të heqësh qasjen për këtë leje."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> po kërkon leje në emër të <xliff:g id="DEVICE_NAME">%2$s</xliff:g> për të transmetuar audion dhe veçoritë e sistemit mes pajisjeve të tua"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ky aplikacion do të mund të sinkronizojë informacione, si p.sh emrin e dikujt që po telefonon, mes telefonit tënd dhe pajisjes së zgjedhur."</string>
     <string name="consent_yes" msgid="8344487259618762872">"Lejo"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 582e832..650d2d8 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Желите да дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; стримује апликације уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ће имати приступ свему што се види или пушта на уређају <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, укључујући звук, слике, информације о плаћању, лозинке и поруке.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ће моћи да стримује апликације на <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> док не уклоните приступ овој дозволи."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> тражи дозволу у име уређаја <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да стримује апликације са уређаја <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Желите да дозволите да &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; стримује звук и системске функције између уређаја <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> и &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ће имати приступ свему што се пушта на уређају <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> ће моћи да стримује звук на <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> док не уклоните приступ овој дозволи."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> тражи дозволу у име уређаја <xliff:g id="DEVICE_NAME">%2$s</xliff:g> да стримује звук и системске функције између уређаја."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ова апликација ће моћи да синхронизује податке, попут имена особе која упућује позив, између телефона и одабраног уређаја"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволи"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index cb7b709..d28bff8 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vill du tillåta &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; att streama appar på din <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> till &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som visas eller spelas upp på <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, inklusive ljud, foton, betalningsuppgifter, lösenord och meddelanden.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan streama appar till <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att streama appar från din <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Vill du tillåta att &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; streamar ljud och systemfunktioner mellan <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> och &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> får åtkomst till allt som spelas upp på din <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> kan streama ljud till <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> tills du tar bort åtkomsten till den här behörigheten."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> begär behörighet för <xliff:g id="DEVICE_NAME">%2$s</xliff:g> att streama ljud och systemfunktioner mellan dina enheter."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Den här appen kommer att kunna synkronisera information mellan telefonen och den valda enheten, till exempel namnet på någon som ringer"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Tillåt"</string>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index 6d623e5..afa3ea6 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Ungependa kuruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; itiririshe programu za <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yako kwenye &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Programu ya <xliff:g id="APP_NAME_0">%1$s</xliff:g> itafikia chochote kinachoonekana au kuchezwa kwenye <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, ikiwa ni pamoja na sauti, picha, maelezo ya malipo, manenosiri na ujumbe.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> itaweza kutiririsha programu kwenye <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hadi utakapoondoa ruhusa hii."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ili itiririshe programu kwenye <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> yako"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Ungependa kuruhusu &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; itiririshe sauti na vipengele vya mfumo kati ya <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> na &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; yako?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> itafikia chochote kinachochezwa kwenye <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> yako.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> itaweza kutiririsha sauti kwenye <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hadi utakapoondoa ruhusa hii."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Programu ya <xliff:g id="APP_NAME">%1$s</xliff:g> inaomba ruhusa kwa niaba ya <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ili itiririshe sauti na vipengele vya mfumo kati ya vifaa vyako."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Programu hii itaweza kusawazisha maelezo, kama vile jina la mtu anayepiga simu, kati ya simu yako na kifaa ulichochagua"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ruhusu"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index 202ec79..fd2038a 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> சாதனத்தின் ஆப்ஸை &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; சாதனத்தில் ஸ்ட்ரீம் செய்ய &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"ஆடியோ, படங்கள், பேமெண்ட் தகவல்கள், கடவுச்சொற்கள், மெசேஜ்கள் உட்பட <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> சாதனத்தில் காட்டப்படுகின்ற/பிளே செய்யப்படுகின்ற அனைத்தையும் <xliff:g id="APP_NAME_0">%1$s</xliff:g> அணுகும்.&lt;br/&gt;&lt;br/&gt;இந்த அனுமதிக்கான அணுகலை நீங்கள் அகற்றும் வரை <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> சாதனத்தில் ஆப்ஸை <xliff:g id="APP_NAME_2">%1$s</xliff:g> ஸ்ட்ரீம் செய்ய முடியும்."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"உங்கள் <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> சாதனத்தில் இருந்து ஆப்ஸை ஸ்ட்ரீம் செய்ய உங்கள் <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கேட்கிறது"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"உங்கள் <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> மற்றும் &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; சாதனங்களுக்கு இடையே ஆடியோவையும் சிஸ்டம் அம்சங்களையும் ஸ்ட்ரீம் செய்ய &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"உங்கள் <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> சாதனத்தில் பிளே ஆகும் அனைத்திற்குமான அணுகலை <xliff:g id="APP_NAME_0">%1$s</xliff:g> கொண்டிருக்கும்.&lt;br/&gt;&lt;br/&gt;இந்த அனுமதிக்கான அணுகலை நீங்கள் அகற்றும் வரை <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> சாதனத்தில் ஆடியோவை <xliff:g id="APP_NAME_2">%1$s</xliff:g> ஸ்ட்ரீம் செய்ய முடியும்."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"உங்கள் சாதனங்களுக்கு இடையே ஆடியோவையும் சிஸ்டம் அம்சங்களையும் ஸ்ட்ரீம் செய்ய <xliff:g id="DEVICE_NAME">%2$s</xliff:g> சார்பாக <xliff:g id="APP_NAME">%1$s</xliff:g> அனுமதி கேட்கிறது."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
     <string name="summary_generic" msgid="1761976003668044801">"அழைப்பவரின் பெயர் போன்ற தகவலை உங்கள் மொபைல் மற்றும் தேர்வுசெய்த சாதனத்திற்கு இடையில் இந்த ஆப்ஸால் ஒத்திசைக்க முடியும்"</string>
     <string name="consent_yes" msgid="8344487259618762872">"அனுமதி"</string>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index 34671f9..8466921 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> యాప్‌లను &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;‌కు స్ట్రీమ్ చేయడానికి &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;‌ను అనుమతించాలా?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"ఆడియో, ఫోటోలు, పేమెంట్ సమాచారం, పాస్‌వర్డ్‌లతో సహా <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>‌లో కనిపించే లేదా ప్లే అయ్యే దేనికైనా <xliff:g id="APP_NAME_0">%1$s</xliff:g>‌కు యాక్సెస్ ఉంటుంది.&lt;br/&gt;&lt;br/&gt;మీరు ఈ అనుమతికి యాక్సెస్‌ను తీసివేసే వరకు <xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>‌కు యాప్‌లను స్ట్రీమ్ చేయగలదు."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"మీ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> నుండి యాప్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> తరఫున అనుమతిని రిక్వెస్ట్ చేస్తోంది"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"మీ <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>, &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; మధ్య ఆడియో, సిస్టమ్ ఫీచర్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g>‌ను అనుమతించాలా?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> మీ <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>‌లో ప్లే చేయబడిన దేనికైనా యాక్సెస్ కలిగి ఉంటుంది.&lt;br/&gt;&lt;br/&gt;మీరు ఈ అనుమతికి యాక్సెస్‌ను తీసివేసే వరకు <xliff:g id="APP_NAME_2">%1$s</xliff:g> ఆడియోను <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>‌కు స్ట్రీమ్ చేయగలదు."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"మీ పరికరాల మధ్య ఆడియో, సిస్టమ్ ఫీచర్‌లను స్ట్రీమ్ చేయడానికి <xliff:g id="DEVICE_NAME">%2$s</xliff:g> తరపున <xliff:g id="APP_NAME">%1$s</xliff:g> యాప్ అనుమతిని రిక్వెస్ట్ చేస్తోంది."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
     <string name="summary_generic" msgid="1761976003668044801">"కాల్ చేస్తున్న వారి పేరు వంటి సమాచారాన్ని ఈ యాప్ మీ ఫోన్ కు, ఎంచుకున్న పరికరానికీ మధ్య సింక్ చేయగలుగుతుంది"</string>
     <string name="consent_yes" msgid="8344487259618762872">"అనుమతించండి"</string>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index e74f96c..2e7ba3c 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; สตรีมแอปใน<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>ของคุณไปยัง &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ไหม"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> จะมีสิทธิ์เข้าถึงทุกอย่างที่ปรากฏหรือเล่นบน <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ซึ่งรวมถึงเสียง รูปภาพ ข้อมูลการชำระเงิน รหัสผ่าน และข้อความ&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> จะสามารถสตรีมแอปไปยัง <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ได้จนกว่าคุณจะนำการให้สิทธิ์นี้ออก"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> เพื่อสตรีมแอปจาก<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>ของคุณ"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"อนุญาตให้ &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; สตรีมเสียงและฟีเจอร์ของระบบระหว่าง<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>กับ &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; ไหม"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> จะมีสิทธิ์เข้าถึงทุกอย่างที่เล่นบน <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> จะสามารถสตรีมเสียงไปยัง <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> ได้จนกว่าคุณจะนำการให้สิทธิ์นี้ออก"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังขอสิทธิ์ในนามของ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> เพื่อสตรีมเสียงและฟีเจอร์ของระบบระหว่างอุปกรณ์ต่างๆ ของคุณ"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
     <string name="summary_generic" msgid="1761976003668044801">"แอปนี้จะสามารถซิงค์ข้อมูล เช่น ชื่อของบุคคลที่โทรเข้ามา ระหว่างโทรศัพท์ของคุณและอุปกรณ์ที่เลือกไว้ได้"</string>
     <string name="consent_yes" msgid="8344487259618762872">"อนุญาต"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index ce907f7..3f4e2af 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na i-stream ang mga app ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> sa &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Magkakaroon ng access ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> sa kahit anong nakikita o pine-play sa <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, kasama ang audio, mga larawan, impormasyon sa pagbabayad, mga password, at mga mensahe.&lt;br/&gt;&lt;br/&gt;Magagawa ng <xliff:g id="APP_NAME_2">%1$s</xliff:g> na mag-stream ng mga app sa <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hanggang sa alisin mo ang access sa pahintulot na ito."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Humihingi ang <xliff:g id="APP_NAME">%1$s</xliff:g> ng pahintulot para sa <xliff:g id="DEVICE_NAME">%2$s</xliff:g> na mag-stream ng mga app mula sa iyong <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Payagan ang &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; na mag-stream ng audio at mga feature ng system sa pagitan ng iyong <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> at &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Magkakaroon ng access ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> sa anumang pine-play sa iyong <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>.&lt;br/&gt;&lt;br/&gt;Makakapag-stream ang <xliff:g id="APP_NAME_2">%1$s</xliff:g> ng audio sa <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> hanggang sa alisin mo ang access sa pahintulot na ito."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Humihingi ang <xliff:g id="APP_NAME">%1$s</xliff:g> ng pahintulot para sa <xliff:g id="DEVICE_NAME">%2$s</xliff:g> na mag-stream ng audio at mga feature ng system sa pagitan ng iyong mga device."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Magagawa ng app na ito na mag-sync ng impormasyon, tulad ng pangalan ng isang taong tumatawag, sa pagitan ng iyong telepono at ng napiling device"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Payagan"</string>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 7acad64..3e4603b 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; adlı uygulamanın <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> cihazınızdaki uygulamaları &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; cihazına aktarmasına izin verilsin mi?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>; ses, fotoğraflar, ödeme bilgileri, şifreler ve mesajlar da dahil olmak üzere <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> cihazında görünen veya oynatılan her şeye erişebilecek.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> siz bu iznin erişimini kaldırana kadar uygulamaları <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cihazına aktarabilecek."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> adına uygulamaları <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> cihazınızdan aktarmak için izin istiyor"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; uygulamasının, <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ve &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; cihazları arasında ses ve sistem özelliklerini aktarmasına izin verilsin mi?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> uygulaması; <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> cihazınızda oynatılan her şeye erişebilecek.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> uygulaması bu iznin erişimini kaldırana kadar sesleri <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cihazına aktarabilecek."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması, <xliff:g id="DEVICE_NAME">%2$s</xliff:g> için cihazlarınız arasında ses ve sistem özelliklerini aktarma izni istiyor."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Bu uygulama, arayan kişinin adı gibi bilgileri telefonunuz ve seçili cihaz arasında senkronize edebilir"</string>
     <string name="consent_yes" msgid="8344487259618762872">"İzin ver"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index 50f93d5..18adf00 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Дозволити додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслювати додатки на вашому <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> на пристрій &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g> матиме доступ до контенту, що відображається чи відтворюється на пристрої \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\", зокрема до аудіо, фото, платіжної інформації, паролів і повідомлень.&lt;br/&gt;&lt;br/&gt;Додаток <xliff:g id="APP_NAME_2">%1$s</xliff:g> зможе транслювати додатки на пристрій \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", поки ви не скасуєте цей дозвіл."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запитує дозвіл на трансляцію додатків на вашому <xliff:g id="DEVICE_TYPE">%3$s</xliff:g>"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Дозволити додатку &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; транслювати аудіо й системні функції між пристроями (<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> і &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;)?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"Додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g> матиме доступ до контенту, що відтворюється на пристрої \"<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>\".&lt;br/&gt;&lt;br/&gt;Додаток <xliff:g id="APP_NAME_2">%1$s</xliff:g> зможе транслювати аудіо на пристрій \"<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>\", поки ви не скасуєте цей дозвіл."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> від імені пристрою \"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>\" запитує дозвіл на трансляцію аудіо й системних функцій між вашими пристроями."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Цей додаток зможе синхронізувати інформацію (наприклад, ім’я абонента, який викликає) між телефоном і вибраним пристроєм"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Дозволити"</string>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 24fd827..cb1a527 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"‏&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; کو آپ کے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> کی ایپس کو <xliff:g id="DEVICE_NAME">%3$s</xliff:g> پر سلسلہ بندی کرنے کی اجازت دیں؟"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"‏<xliff:g id="APP_NAME_0">%1$s</xliff:g> کو <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> پر دکھائی دینے والی یا چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی، بشمول آڈیو، تصاویر، ادائیگی کی معلومات، پاس ورڈز اور پیغامات۔&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> پر اس وقت تک ایپس کی سلسلہ بندی کر سکے گی جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> کی جانب سے آپ کے <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> سے ایپس کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"‏اپنے <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> اور ‎&lt;strong&gt;‎<xliff:g id="DEVICE_NAME">%3$s</xliff:g>‏‎&lt;/strong&gt;‎ کے درمیان آڈیو اور سسٹم کی خصوصیات کی سلسلہ بندی کرنے کی ‎&lt;strong&gt;‎<xliff:g id="APP_NAME">%1$s</xliff:g>‏‎&lt;/strong&gt;‎ کو اجازت دیں؟"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"‏‫<xliff:g id="APP_NAME_0">%1$s</xliff:g> کو آپ کے <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> پر چلائی جانے والی کسی بھی چیز تک رسائی حاصل ہوگی۔‎&lt;br/&gt;&lt;br/&gt;‎<xliff:g id="APP_NAME_2">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> پر اس وقت تک آڈیو کی سلسلہ بندی کر سکے گی جب تک آپ اس اجازت تک رسائی کو ہٹا نہیں دیتے۔"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"‫<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ <xliff:g id="DEVICE_NAME">%2$s</xliff:g> کی جانب سے آپ کے آلات کے درمیان آڈیو اور سسٹم کی خصوصیات کی سلسلہ بندی کرنے کی اجازت کی درخواست کر رہی ہے۔"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
     <string name="summary_generic" msgid="1761976003668044801">"یہ ایپ آپ کے فون اور منتخب کردہ آلے کے درمیان معلومات، جیسے کسی کال کرنے والے کے نام، کی مطابقت پذیری کر سکے گی"</string>
     <string name="consent_yes" msgid="8344487259618762872">"اجازت دیں"</string>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 3335551..993c502 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; <xliff:g id="DEVICE_TYPE">%2$s</xliff:g>dagi ilovalarni &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; qurilmasiga striming qilishiga ruxsat berasizmi?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>da koʻrinadigan yoki ijro etiladigan hamma narsaga, jumladan, audio, rasmlar, parollar va xabarlarga kirish huquqini oladi.&lt;br/&gt;&lt;br/&gt;Bu ruxsatni olib tashlamaguningizcha, <xliff:g id="APP_NAME_2">%1$s</xliff:g> ilovalarni <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> qurilmasiga striming qila oladi."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nomidan <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> orqali ilovalarni uzatish uchun ruxsat olmoqchi"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Siz &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ilovasiga <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> va &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; qurilmalari orasida audio striming qilish va tizim funksiyalariga ruxsat berasizmi?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> qurilmangizda ijro etiladigan hamma narsaga kira oladi.&lt;br/&gt;&lt;br/&gt;Bu ruxsatni olib tashlamaguningizcha <xliff:g id="APP_NAME_2">%1$s</xliff:g> ilovasi <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> qurilmasiga audio striming qila oladi."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> audio striming va qurilmalaringiz orasidagi tizim funksiyalari uchun <xliff:g id="DEVICE_NAME">%2$s</xliff:g> nomidan ruxsat soʻramoqda."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Bu ilova telefoningiz va tanlangan qurilmada chaqiruvchining ismi kabi maʼlumotlarni sinxronlay oladi"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Ruxsat"</string>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index 7f6d5b1..dee65de 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truyền trực tuyến các ứng dụng trên <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> của bạn đến &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sẽ có quyền truy cập vào mọi nội dung hiển thị hoặc phát trên <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, bao gồm cả âm thanh, ảnh, thông tin thanh toán, mật khẩu và tin nhắn.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sẽ có thể truyền trực tuyến các ứng dụng đến <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cho đến khi bạn thu hồi quyền này."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_NAME">%2$s</xliff:g> để truyền trực tuyến các ứng dụng từ <xliff:g id="DEVICE_TYPE">%3$s</xliff:g> của bạn"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Cho phép &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; truyền trực tuyến âm thanh và các tính năng của hệ thống giữa <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> và &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> sẽ có quyền truy cập vào mọi nội dung được phát trên <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> của bạn.&lt;br/&gt;&lt;br/&gt;<xliff:g id="APP_NAME_2">%1$s</xliff:g> sẽ có thể truyền trực tuyến âm thanh đến <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> cho đến khi bạn thu hồi quyền này."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang yêu cầu quyền thay cho <xliff:g id="DEVICE_NAME">%2$s</xliff:g> để truyền trực tuyến âm thanh và những tính năng khác của hệ thống giữa các thiết bị của bạn."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Ứng dụng này sẽ đồng bộ hoá thông tin (ví dụ: tên người gọi) giữa điện thoại của bạn và thiết bị bạn chọn"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Cho phép"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index c54c452..605cab7 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;将您的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>上的应用流式传输到&lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;吗?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"“<xliff:g id="APP_NAME_0">%1$s</xliff:g>”将能够访问“<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>”上显示或播放的任何内容,包括音频、照片、付款信息、密码和消息。&lt;br/&gt;&lt;br/&gt;“<xliff:g id="APP_NAME_2">%1$s</xliff:g>”可将应用流式传输到“<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>”,除非您撤消此访问权限。"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”请求获得从您的<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>流式传输应用的权限"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"要允许&lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;在<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>和&lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;之间流式传输音频和系统功能吗?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"“<xliff:g id="APP_NAME_0">%1$s</xliff:g>”将能够访问“<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>”上播放的任何内容。&lt;br/&gt;&lt;br/&gt;“<xliff:g id="APP_NAME_2">%1$s</xliff:g>”能够将音频流式传输到“<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>”,除非您撤消此访问权限。"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正代表“<xliff:g id="DEVICE_NAME">%2$s</xliff:g>”请求在设备之间流式传输音频和系统功能。"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
     <string name="summary_generic" msgid="1761976003668044801">"此应用将能在您的手机和所选设备之间同步信息,例如来电者的姓名"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允许"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index e47dfa0..d1c73e5 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」串流<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>應用程式內容至 <xliff:g id="DEVICE_NAME">%3$s</xliff:g> 嗎?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將能存取「<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>」上顯示或播放的任何內容,包括音訊、相片、付款資料、密碼和訊息。&lt;br/&gt;&lt;br/&gt;「<xliff:g id="APP_NAME_2">%1$s</xliff:g>」將能串流應用程式內容至 <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>,直至你移除此存取權限為止。"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求權限,以便從你的<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>串流應用程式內容"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;在你的<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>和 <xliff:g id="DEVICE_NAME">%3$s</xliff:g> 之間串流音訊和系統功能嗎&lt;strong&gt;&lt;/strong&gt;?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將能存取 <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> 上播放的任何內容。&lt;br/&gt;&lt;br/&gt;「<xliff:g id="APP_NAME_2">%1$s</xliff:g>」將能串流音訊至「<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>」,直至你移除此存取權限為止。"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求權限,以便在裝置之間串流音訊和系統功能。"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
     <string name="summary_generic" msgid="1761976003668044801">"此應用程式將可同步手機和所選裝置的資訊,例如來電者的名稱"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index b91024a..c675fed 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;將<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>的應用程式串流傳輸到 &lt;strong&gt;<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt; 嗎?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將可存取 <xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> 顯示或播放的所有內容,包括音訊、相片、付款資訊、密碼和訊息。&lt;br/&gt;&lt;br/&gt;「<xliff:g id="APP_NAME_2">%1$s</xliff:g>」可將應用程式串流傳輸到 <xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>,直到你移除這個權限為止。"</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表 <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 要求必要權限,以便從<xliff:g id="DEVICE_TYPE">%3$s</xliff:g>串流傳輸應用程式"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;在<xliff:g id="DEVICE_TYPE">%2$s</xliff:g>和「<xliff:g id="DEVICE_NAME">%3$s</xliff:g>」&lt;strong&gt;&lt;/strong&gt;間串流傳輸音訊和系統功能嗎?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」將可存取「<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>」播放的所有內容。&lt;br/&gt;&lt;br/&gt;「<xliff:g id="APP_NAME_2">%1$s</xliff:g>」可將音訊串流傳輸到「<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g>」,直到你移除這個權限為止。"</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在代表「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」要求必要權限,以便在裝置間串流傳輸音訊和系統功能。"</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
     <string name="summary_generic" msgid="1761976003668044801">"這個應用程式將可在手機和指定裝置間同步資訊,例如來電者名稱"</string>
     <string name="consent_yes" msgid="8344487259618762872">"允許"</string>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index 160332e..365b2f4 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -36,6 +36,9 @@
     <string name="title_nearby_device_streaming" msgid="2727103756701741359">"Vumela &lt;strong&gt;i-<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; ukuze isakaze ama-app e-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> yakho &lt;strong&gt;ku-<xliff:g id="DEVICE_NAME">%3$s</xliff:g>&lt;/strong&gt;?"</string>
     <string name="summary_nearby_device_streaming" msgid="70434958004946884">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> izokwazi ukufinyelela kunoma yini ebonakalayo noma edlalwayo ku-<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g>, okuhlanganisa umsindo, izithombe, ulwazi lokukhokha, amaphasiwedi, nemilayezo.&lt;br/&gt;&lt;br/&gt;I-<xliff:g id="APP_NAME_2">%1$s</xliff:g> izokwazi ukusakaza ama-app ku-<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> uze ususe ukufinyelela kule mvume."</string>
     <string name="helper_summary_nearby_device_streaming" msgid="4712712177819370967">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ukuze isakaze ama-app nezakhi ukusuka ku-<xliff:g id="DEVICE_TYPE">%3$s</xliff:g> yakho"</string>
+    <string name="title_sensor_device_streaming" msgid="2395553261097861497">"Uvumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukuthi isakaze izakhi zomsindo nesistimu phakathi kwe-<xliff:g id="DEVICE_TYPE">%2$s</xliff:g> ne-<xliff:g id="DEVICE_NAME">%3$s</xliff:g>?"</string>
+    <string name="summary_sensor_device_streaming" msgid="3413105061195145547">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> izokwazi ukufinyelela kunoma yini edlalwa ku-<xliff:g id="DEVICE_NAME_1">%3$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%1$s</xliff:g> yakho futhi izokwazi ukusakaza umsindo ku-<xliff:g id="DEVICE_NAME_3">%3$s</xliff:g> uze ususe ukufinyelela kule mvume."</string>
+    <string name="helper_summary_sensor_device_streaming" msgid="8860174545653786353">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> icela imvume esikhundleni se-<xliff:g id="DEVICE_NAME">%2$s</xliff:g> ukuze isakaze izakhi zomsindo nesistimu phakathi kwamadivayisi akho."</string>
     <string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
     <string name="summary_generic" msgid="1761976003668044801">"Le app izokwazi ukuvumelanisa ulwazi, njengegama lomuntu othile ofonayo, phakathi kwefoni yakho nedivayisi ekhethiwe"</string>
     <string name="consent_yes" msgid="8344487259618762872">"Vumela"</string>
diff --git a/packages/CrashRecovery/framework/api/system-current.txt b/packages/CrashRecovery/framework/api/system-current.txt
index 68429ea..ad17ec69 100644
--- a/packages/CrashRecovery/framework/api/system-current.txt
+++ b/packages/CrashRecovery/framework/api/system-current.txt
@@ -9,7 +9,7 @@
     method @NonNull public abstract java.util.List<java.lang.String> onGetRequestedPackages();
     method @NonNull public abstract java.util.List<android.service.watchdog.ExplicitHealthCheckService.PackageConfig> onGetSupportedPackages();
     method public abstract void onRequestHealthCheck(@NonNull String);
-    method @FlaggedApi("android.crashrecovery.flags.enable_crashrecovery") public final void setHealthCheckResultCallback(@Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<android.os.Bundle>);
+    method @FlaggedApi("android.crashrecovery.flags.enable_crashrecovery") public final void setHealthCheckPassedCallback(@Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<android.os.Bundle>);
     field public static final String BIND_PERMISSION = "android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE";
     field @FlaggedApi("android.crashrecovery.flags.enable_crashrecovery") public static final String EXTRA_HEALTH_CHECK_PASSED_PACKAGE = "android.service.watchdog.extra.HEALTH_CHECK_PASSED_PACKAGE";
     field public static final String SERVICE_INTERFACE = "android.service.watchdog.ExplicitHealthCheckService";
diff --git a/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java
index b03e376..fdb0fc5 100644
--- a/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java
+++ b/packages/CrashRecovery/framework/java/android/service/watchdog/ExplicitHealthCheckService.java
@@ -180,7 +180,7 @@
      *                 passed the health check.
      */
     @FlaggedApi(Flags.FLAG_ENABLE_CRASHRECOVERY)
-    public final void setHealthCheckResultCallback(@CallbackExecutor @Nullable Executor executor,
+    public final void setHealthCheckPassedCallback(@CallbackExecutor @Nullable Executor executor,
             @Nullable Consumer<Bundle> callback) {
         mCallbackExecutor = executor;
         mHealthCheckResultCallback = callback;
diff --git a/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java
index 31e1eb3..ef46906 100644
--- a/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/module/java/com/android/server/PackageWatchdog.java
@@ -347,8 +347,8 @@
      *                 and boot loops.
      * @param executor Executor for the thread on which observers would receive callbacks
      */
-    public void registerHealthObserver(@NonNull PackageHealthObserver observer,
-            @NonNull @CallbackExecutor Executor executor) {
+    public void registerHealthObserver(@NonNull @CallbackExecutor Executor executor,
+            @NonNull PackageHealthObserver observer) {
         synchronized (sLock) {
             ObserverInternal internalObserver = mAllObservers.get(observer.getUniqueIdentifier());
             if (internalObserver != null) {
@@ -390,8 +390,8 @@
      *
      * @throws IllegalStateException if the observer was not previously registered
      */
-    public void startExplicitHealthCheck(@NonNull PackageHealthObserver observer,
-            @NonNull List<String> packageNames, long timeoutMs) {
+    public void startExplicitHealthCheck(@NonNull List<String> packageNames, long timeoutMs,
+            @NonNull PackageHealthObserver observer) {
         synchronized (sLock) {
             if (!mAllObservers.containsKey(observer.getUniqueIdentifier())) {
                 Slog.wtf(TAG, "No observer found, need to register the observer: "
@@ -767,14 +767,6 @@
     }
 
     /**
-     * Indicates that the result of a mitigation executed during
-     * {@link PackageHealthObserver#onExecuteHealthCheckMitigation} or
-     * {@link PackageHealthObserver#onExecuteBootLoopMitigation} is unknown.
-     */
-    public static final int MITIGATION_RESULT_UNKNOWN =
-            ObserverMitigationResult.MITIGATION_RESULT_UNKNOWN;
-
-    /**
      * Indicates that a mitigation was successfully triggered or executed during
      * {@link PackageHealthObserver#onExecuteHealthCheckMitigation} or
      * {@link PackageHealthObserver#onExecuteBootLoopMitigation}.
@@ -790,23 +782,6 @@
     public static final int MITIGATION_RESULT_SKIPPED =
             ObserverMitigationResult.MITIGATION_RESULT_SKIPPED;
 
-    /**
-     * Indicates that a mitigation executed during
-     * {@link PackageHealthObserver#onExecuteHealthCheckMitigation} or
-     * {@link PackageHealthObserver#onExecuteBootLoopMitigation} failed,
-     * but the failure is potentially retryable.
-     */
-    public static final int MITIGATION_RESULT_FAILURE_RETRYABLE =
-            ObserverMitigationResult.MITIGATION_RESULT_FAILURE_RETRYABLE;
-
-    /**
-     * Indicates that a mitigation executed during
-     * {@link PackageHealthObserver#onExecuteHealthCheckMitigation} or
-     * {@link PackageHealthObserver#onExecuteBootLoopMitigation} failed,
-     * and the failure is not retryable.
-     */
-    public static final int MITIGATION_RESULT_FAILURE_NON_RETRYABLE =
-            ObserverMitigationResult.MITIGATION_RESULT_FAILURE_NON_RETRYABLE;
 
     /**
      * Possible return values of the for mitigations executed during
@@ -816,18 +791,12 @@
      */
     @Retention(SOURCE)
     @IntDef(prefix = "MITIGATION_RESULT_", value = {
-            ObserverMitigationResult.MITIGATION_RESULT_UNKNOWN,
             ObserverMitigationResult.MITIGATION_RESULT_SUCCESS,
             ObserverMitigationResult.MITIGATION_RESULT_SKIPPED,
-            ObserverMitigationResult.MITIGATION_RESULT_FAILURE_RETRYABLE,
-            ObserverMitigationResult.MITIGATION_RESULT_FAILURE_NON_RETRYABLE,
             })
     public @interface ObserverMitigationResult {
-        int MITIGATION_RESULT_UNKNOWN = 0;
         int MITIGATION_RESULT_SUCCESS = 1;
         int MITIGATION_RESULT_SKIPPED = 2;
-        int MITIGATION_RESULT_FAILURE_RETRYABLE = 3;
-        int MITIGATION_RESULT_FAILURE_NON_RETRYABLE = 4;
     }
 
     /**
@@ -921,11 +890,6 @@
          * @param mitigationCount the number of times mitigation has been called for this package
          *                         (including this time).
          * @return {@link #MITIGATION_RESULT_SUCCESS} if the mitigation was successful,
-         *         {@link #MITIGATION_RESULT_FAILURE_RETRYABLE} if the mitigation failed but can be
-         *         retried,
-         *         {@link #MITIGATION_RESULT_FAILURE_NON_RETRYABLE} if the mitigation failed and
-         *         cannot be retried,
-         *         {@link #MITIGATION_RESULT_UNKNOWN} if the result of the mitigation is unknown,
          *         or {@link #MITIGATION_RESULT_SKIPPED} if the mitigation was skipped.
          */
         @ObserverMitigationResult int onExecuteHealthCheckMitigation(
@@ -957,11 +921,6 @@
          *                        boot loop (including this time).
          *
          * @return {@link #MITIGATION_RESULT_SUCCESS} if the mitigation was successful,
-         *         {@link #MITIGATION_RESULT_FAILURE_RETRYABLE} if the mitigation failed but can be
-         *         retried,
-         *         {@link #MITIGATION_RESULT_FAILURE_NON_RETRYABLE} if the mitigation failed and
-         *         cannot be retried,
-         *         {@link #MITIGATION_RESULT_UNKNOWN} if the result of the mitigation is unknown,
          *         or {@link #MITIGATION_RESULT_SKIPPED} if the mitigation was skipped.
          */
         default @ObserverMitigationResult int onExecuteBootLoopMitigation(int mitigationCount) {
@@ -2074,15 +2033,19 @@
             bootMitigationCounts.put(observer.name, observer.getBootMitigationCount());
         }
 
+        FileOutputStream fileStream = null;
+        ObjectOutputStream objectStream = null;
         try {
-            FileOutputStream fileStream = new FileOutputStream(new File(filePath));
-            ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
+            fileStream = new FileOutputStream(new File(filePath));
+            objectStream = new ObjectOutputStream(fileStream);
             objectStream.writeObject(bootMitigationCounts);
             objectStream.flush();
-            objectStream.close();
-            fileStream.close();
         } catch (Exception e) {
             Slog.i(TAG, "Could not save observers metadata to file: " + e);
+            return;
+        } finally {
+            IoUtils.closeQuietly(objectStream);
+            IoUtils.closeQuietly(fileStream);
         }
     }
 
@@ -2233,23 +2196,32 @@
         void readAllObserversBootMitigationCountIfNecessary(String filePath) {
             File metadataFile = new File(filePath);
             if (metadataFile.exists()) {
+                FileInputStream fileStream = null;
+                ObjectInputStream objectStream = null;
+                HashMap<String, Integer> bootMitigationCounts = null;
                 try {
-                    FileInputStream fileStream = new FileInputStream(metadataFile);
-                    ObjectInputStream objectStream = new ObjectInputStream(fileStream);
-                    HashMap<String, Integer> bootMitigationCounts =
+                    fileStream = new FileInputStream(metadataFile);
+                    objectStream = new ObjectInputStream(fileStream);
+                    bootMitigationCounts =
                             (HashMap<String, Integer>) objectStream.readObject();
-                    objectStream.close();
-                    fileStream.close();
-
-                    for (int i = 0; i < mAllObservers.size(); i++) {
-                        final ObserverInternal observer = mAllObservers.valueAt(i);
-                        if (bootMitigationCounts.containsKey(observer.name)) {
-                            observer.setBootMitigationCount(
-                                    bootMitigationCounts.get(observer.name));
-                        }
-                    }
                 } catch (Exception e) {
                     Slog.i(TAG, "Could not read observer metadata file: " + e);
+                   return;
+                } finally {
+                    IoUtils.closeQuietly(objectStream);
+                    IoUtils.closeQuietly(fileStream);
+                }
+
+                if (bootMitigationCounts == null || bootMitigationCounts.isEmpty()) {
+                    Slog.i(TAG, "No observer in metadata file");
+                    return;
+                }
+                for (int i = 0; i < mAllObservers.size(); i++) {
+                    final ObserverInternal observer = mAllObservers.valueAt(i);
+                    if (bootMitigationCounts.containsKey(observer.name)) {
+                        observer.setBootMitigationCount(
+                                bootMitigationCounts.get(observer.name));
+                    }
                 }
             }
         }
diff --git a/packages/CrashRecovery/services/module/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/module/java/com/android/server/RescueParty.java
index bb9e962..40bc5f7 100644
--- a/packages/CrashRecovery/services/module/java/com/android/server/RescueParty.java
+++ b/packages/CrashRecovery/services/module/java/com/android/server/RescueParty.java
@@ -162,7 +162,7 @@
     /** Register the Rescue Party observer as a Package Watchdog health observer */
     public static void registerHealthObserver(Context context) {
         PackageWatchdog.getInstance(context).registerHealthObserver(
-                RescuePartyObserver.getInstance(context), context.getMainExecutor());
+                context.getMainExecutor(), RescuePartyObserver.getInstance(context));
     }
 
     private static boolean isDisabled() {
@@ -316,9 +316,9 @@
             Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
                     + updatedNamespace);
             PackageWatchdog.getInstance(context).startExplicitHealthCheck(
-                    rescuePartyObserver,
                     callingPackageList,
-                    DEFAULT_OBSERVING_DURATION_MS);
+                    DEFAULT_OBSERVING_DURATION_MS,
+                    rescuePartyObserver);
         }
     }
 
diff --git a/packages/CrashRecovery/services/module/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/module/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index c75f3aa..4978df4 100644
--- a/packages/CrashRecovery/services/module/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/packages/CrashRecovery/services/module/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -113,8 +113,8 @@
         dataDir.mkdirs();
         mLastStagedRollbackIdsFile = new File(dataDir, "last-staged-rollback-ids");
         mTwoPhaseRollbackEnabledFile = new File(dataDir, "two-phase-rollback-enabled");
-        PackageWatchdog.getInstance(mContext).registerHealthObserver(this,
-                context.getMainExecutor());
+        PackageWatchdog.getInstance(mContext).registerHealthObserver(context.getMainExecutor(),
+                this);
 
         if (SystemProperties.getBoolean("sys.boot_completed", false)) {
             // Load the value from the file if system server has crashed and restarted
diff --git a/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java b/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java
index ffae517..4a00ed3 100644
--- a/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java
+++ b/packages/CrashRecovery/services/platform/java/com/android/server/PackageWatchdog.java
@@ -363,7 +363,7 @@
      * it will resume observing any packages requested from a previous boot.
      * @hide
      */
-    public void registerHealthObserver(PackageHealthObserver observer, Executor ignoredExecutor) {
+    public void registerHealthObserver(Executor ignoredExecutor, PackageHealthObserver observer) {
         synchronized (mLock) {
             ObserverInternal internalObserver = mAllObservers.get(observer.getUniqueIdentifier());
             if (internalObserver != null) {
@@ -397,8 +397,8 @@
      * {@link #DEFAULT_OBSERVING_DURATION_MS} will be used.
      * @hide
      */
-    public void startExplicitHealthCheck(PackageHealthObserver observer, List<String> packageNames,
-            long durationMs) {
+    public void startExplicitHealthCheck(List<String> packageNames, long durationMs,
+            PackageHealthObserver observer) {
         if (packageNames.isEmpty()) {
             Slog.wtf(TAG, "No packages to observe, " + observer.getUniqueIdentifier());
             return;
@@ -446,7 +446,7 @@
             }
 
             // Register observer in case not already registered
-            registerHealthObserver(observer, null);
+            registerHealthObserver(null, observer);
 
             // Sync after we add the new packages to the observers. We may have received packges
             // requiring an earlier schedule than we are currently scheduled for.
@@ -2021,15 +2021,19 @@
             bootMitigationCounts.put(observer.name, observer.getBootMitigationCount());
         }
 
+        FileOutputStream fileStream = null;
+        ObjectOutputStream objectStream = null;
         try {
-            FileOutputStream fileStream = new FileOutputStream(new File(filePath));
-            ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
+            fileStream = new FileOutputStream(new File(filePath));
+            objectStream = new ObjectOutputStream(fileStream);
             objectStream.writeObject(bootMitigationCounts);
             objectStream.flush();
-            objectStream.close();
-            fileStream.close();
         } catch (Exception e) {
             Slog.i(TAG, "Could not save observers metadata to file: " + e);
+            return;
+        } finally {
+            IoUtils.closeQuietly(objectStream);
+            IoUtils.closeQuietly(fileStream);
         }
     }
 
@@ -2180,23 +2184,32 @@
         void readAllObserversBootMitigationCountIfNecessary(String filePath) {
             File metadataFile = new File(filePath);
             if (metadataFile.exists()) {
+                FileInputStream fileStream = null;
+                ObjectInputStream objectStream = null;
+                HashMap<String, Integer> bootMitigationCounts = null;
                 try {
-                    FileInputStream fileStream = new FileInputStream(metadataFile);
-                    ObjectInputStream objectStream = new ObjectInputStream(fileStream);
-                    HashMap<String, Integer> bootMitigationCounts =
+                    fileStream = new FileInputStream(metadataFile);
+                    objectStream = new ObjectInputStream(fileStream);
+                    bootMitigationCounts =
                             (HashMap<String, Integer>) objectStream.readObject();
-                    objectStream.close();
-                    fileStream.close();
-
-                    for (int i = 0; i < mAllObservers.size(); i++) {
-                        final ObserverInternal observer = mAllObservers.valueAt(i);
-                        if (bootMitigationCounts.containsKey(observer.name)) {
-                            observer.setBootMitigationCount(
-                                    bootMitigationCounts.get(observer.name));
-                        }
-                    }
                 } catch (Exception e) {
                     Slog.i(TAG, "Could not read observer metadata file: " + e);
+                    return;
+                } finally {
+                    IoUtils.closeQuietly(objectStream);
+                    IoUtils.closeQuietly(fileStream);
+                }
+
+                if (bootMitigationCounts == null || bootMitigationCounts.isEmpty()) {
+                    Slog.i(TAG, "No observer in metadata file");
+                    return;
+                }
+                for (int i = 0; i < mAllObservers.size(); i++) {
+                    final ObserverInternal observer = mAllObservers.valueAt(i);
+                    if (bootMitigationCounts.containsKey(observer.name)) {
+                        observer.setBootMitigationCount(
+                                bootMitigationCounts.get(observer.name));
+                    }
                 }
             }
         }
diff --git a/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java b/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
index c6452d3..8251fb4 100644
--- a/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
+++ b/packages/CrashRecovery/services/platform/java/com/android/server/RescueParty.java
@@ -168,7 +168,7 @@
     /** Register the Rescue Party observer as a Package Watchdog health observer */
     public static void registerHealthObserver(Context context) {
         PackageWatchdog.getInstance(context).registerHealthObserver(
-                RescuePartyObserver.getInstance(context), null);
+                null, RescuePartyObserver.getInstance(context));
     }
 
     private static boolean isDisabled() {
@@ -390,9 +390,9 @@
             Slog.i(TAG, "Starting to observe: " + callingPackageList + ", updated namespace: "
                     + updatedNamespace);
             PackageWatchdog.getInstance(context).startExplicitHealthCheck(
-                    rescuePartyObserver,
                     callingPackageList,
-                    DEFAULT_OBSERVING_DURATION_MS);
+                    DEFAULT_OBSERVING_DURATION_MS,
+                    rescuePartyObserver);
         }
     }
 
diff --git a/packages/CrashRecovery/services/platform/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/packages/CrashRecovery/services/platform/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 0411537..5c4e57e 100644
--- a/packages/CrashRecovery/services/platform/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/packages/CrashRecovery/services/platform/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -112,7 +112,7 @@
         dataDir.mkdirs();
         mLastStagedRollbackIdsFile = new File(dataDir, "last-staged-rollback-ids");
         mTwoPhaseRollbackEnabledFile = new File(dataDir, "two-phase-rollback-enabled");
-        PackageWatchdog.getInstance(mContext).registerHealthObserver(this, null);
+        PackageWatchdog.getInstance(mContext).registerHealthObserver(null, this);
         mApexManager = apexManager;
 
         if (SystemProperties.getBoolean("sys.boot_completed", false)) {
@@ -286,7 +286,7 @@
     @AnyThread
     @NonNull
     public void startObservingHealth(@NonNull List<String> packages, @NonNull long durationMs) {
-        PackageWatchdog.getInstance(mContext).startExplicitHealthCheck(this, packages, durationMs);
+        PackageWatchdog.getInstance(mContext).startExplicitHealthCheck(packages, durationMs, this);
     }
 
     @AnyThread
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
index 04a2c07..b88fda7 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
@@ -65,8 +65,8 @@
             imageVector = if (toggleState.value)
                 Icons.Outlined.Visibility else Icons.Outlined.VisibilityOff,
             contentDescription = if (toggleState.value)
-                stringResource(R.string.content_description_show_password) else
-                stringResource(R.string.content_description_hide_password),
+                stringResource(R.string.content_description_hide_password) else
+                stringResource(R.string.content_description_show_password),
             tint = MaterialTheme.colorScheme.onSurfaceVariant,
         )
     }
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index e029f3a..4da7359 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -24,6 +24,7 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
     <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
+    <uses-permission android:name="android.permission.RESOLVE_COMPONENT_FOR_UID" />
 
     <uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" />
 
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index 635ae20..6c06fab 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -26,6 +26,7 @@
 import android.content.ContentResolver;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.Flags;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
@@ -274,8 +275,20 @@
     }
 
     private boolean canPackageQuery(int callingUid, Uri packageUri) {
-        ProviderInfo info = mPackageManager.resolveContentProvider(packageUri.getAuthority(),
-                PackageManager.ComponentInfoFlags.of(0));
+        ProviderInfo info;
+        try {
+            if (Flags.uidBasedProviderLookup()) {
+                info = mPackageManager.resolveContentProviderForUid(packageUri.getAuthority(),
+                    PackageManager.ComponentInfoFlags.of(0), callingUid);
+            } else {
+                info = mPackageManager.resolveContentProvider(packageUri.getAuthority(),
+                    PackageManager.ComponentInfoFlags.of(0));
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Caller cannot access " + packageUri, e);
+            return false;
+        }
+
         if (info == null) {
             return false;
         }
diff --git a/packages/SettingsLib/ButtonPreference/Android.bp b/packages/SettingsLib/ButtonPreference/Android.bp
index 0382829..08dd27f 100644
--- a/packages/SettingsLib/ButtonPreference/Android.bp
+++ b/packages/SettingsLib/ButtonPreference/Android.bp
@@ -24,4 +24,8 @@
 
     sdk_version: "system_current",
     min_sdk_version: "21",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.healthfitness",
+    ],
 }
diff --git a/packages/SettingsLib/ButtonPreference/src/com/android/settingslib/widget/ButtonPreference.java b/packages/SettingsLib/ButtonPreference/src/com/android/settingslib/widget/ButtonPreference.java
index 993555e..be711ac 100644
--- a/packages/SettingsLib/ButtonPreference/src/com/android/settingslib/widget/ButtonPreference.java
+++ b/packages/SettingsLib/ButtonPreference/src/com/android/settingslib/widget/ButtonPreference.java
@@ -247,4 +247,28 @@
             mButton.setLayoutParams(lp);
         }
     }
+
+    /**
+     * Sets the style of the button.
+     *
+     * @param type Specifies the button's type, which sets the attribute `buttonPreferenceType`.
+     *             Possible values are:
+     *             <ul>
+     *                 <li>0: filled</li>
+     *                 <li>1: tonal</li>
+     *                 <li>2: outline</li>
+     *             </ul>
+     * @param size Specifies the button's size, which sets the attribute `buttonPreferenceSize`.
+     *             Possible values are:
+     *             <ul>
+     *                 <li>0: normal</li>
+     *                 <li>1: large</li>
+     *                 <li>2: extra large</li>
+     *             </ul>
+     */
+    public void setButtonStyle(int type, int size) {
+        int layoutId = ButtonStyle.getLayoutId(type, size);
+        setLayoutResource(layoutId);
+        notifyChanged();
+    }
 }
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Permissions.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Permissions.kt
new file mode 100644
index 0000000..8716420
--- /dev/null
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/Permissions.kt
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.content.Context
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+
+/**
+ * Class to manage permissions, which supports a combination of AND / OR.
+ *
+ * Samples:
+ * - `Permissions.EMPTY`: no permission is required
+ * - `Permissions.allOf(p1, p2) or p3 or Permissions.allOf(p4, p5)`
+ * - `Permissions.anyOf(p1, p2) and p3 and Permissions.anyOf(p4, p5)`
+ * - `Permissions.allOf(p1, p2) or (Permissions.allOf(p3, p4) and p5)`: ALWAYS add `()` explicitly
+ *   when and/or operators are used at the same time.
+ */
+sealed class Permissions(vararg permissions: Any) {
+    internal val permissions = mutableSetOf(*permissions)
+
+    val size: Int
+        get() = permissions.size
+
+    override fun hashCode() = permissions.hashCode()
+
+    override fun equals(other: Any?) =
+        other is Permissions &&
+            permissions == other.permissions &&
+            (permissions.size == 1 || javaClass == other.javaClass)
+
+    abstract fun check(context: Context, pid: Int, uid: Int): Boolean
+
+    internal fun addForAnd(permission: Any): Permissions =
+        when {
+            // ensure empty permissions will never been modified
+            permissions.isEmpty() -> (permission as? Permissions) ?: AllOfPermissions(permission)
+            permission is Permissions && permission.permissions.isEmpty() -> this
+            this is AllOfPermissions -> apply { and(permission) }
+            permission is AllOfPermissions -> permission.also { it.and(this) }
+            // anyOf(p1) and p2 => allOf(p1, p2)
+            permissions.size == 1 && this is AnyOfPermissions && permission is String ->
+                AllOfPermissions(permissions.first(), permission)
+            // anyOf(p1) and anyOf(p2) => allOf(p1, p2)
+            permissions.size == 1 &&
+                permission is AnyOfPermissions &&
+                permission.permissions.size == 1 ->
+                AllOfPermissions(permissions.first(), permission.permissions.first())
+            else -> AllOfPermissions(this, permission)
+        }
+
+    internal fun addForOr(permission: Any): Permissions =
+        when {
+            // ensure empty permissions will never been modified
+            permissions.isEmpty() -> (permission as? Permissions) ?: AnyOfPermissions(permission)
+            permission is Permissions && permission.permissions.isEmpty() -> this
+            this is AnyOfPermissions -> apply { or(permission) }
+            permission is AnyOfPermissions -> permission.also { it.or(this) }
+            // allOf(p1) or p2 => anyOf(p1, p2)
+            permissions.size == 1 && this is AllOfPermissions && permission is String ->
+                AnyOfPermissions(permissions.first(), permission)
+            // allOf(p1) or allOf(p2) => anyOf(p1, p2)
+            permissions.size == 1 &&
+                permission is AllOfPermissions &&
+                permission.permissions.size == 1 ->
+                AnyOfPermissions(permissions.first(), permission.permissions.first())
+            else -> AnyOfPermissions(this, permission)
+        }
+
+    protected fun Any.check(context: Context, pid: Int, uid: Int) =
+        when (this) {
+            is String -> context.checkPermission(this, pid, uid) == PERMISSION_GRANTED
+            else -> (this as Permissions).check(context, pid, uid)
+        }
+
+    fun forEach(action: (Any) -> Unit) {
+        for (permission in permissions) action(permission)
+    }
+
+    companion object {
+        /** Returns [Permissions] that requires all of the permissions. */
+        fun allOf(vararg permissions: String): Permissions =
+            if (permissions.isEmpty()) EMPTY else AllOfPermissions(*permissions)
+
+        /** Returns [Permissions] that requires any of the permissions. */
+        fun anyOf(vararg permissions: String): Permissions =
+            if (permissions.isEmpty()) EMPTY else AnyOfPermissions(*permissions)
+
+        /** No permission required. */
+        val EMPTY: Permissions = AllOfPermissions()
+    }
+}
+
+class AllOfPermissions internal constructor(vararg permissions: Any) : Permissions(*permissions) {
+
+    override fun toString() = permissions.joinToString(prefix = "allOf(", postfix = ")")
+
+    override fun check(context: Context, pid: Int, uid: Int): Boolean {
+        // use for-loop explicitly instead of "all" extension for empty permissions
+        for (permission in permissions) {
+            if (!permission.check(context, pid, uid)) return false
+        }
+        return true
+    }
+
+    internal fun and(permission: Any) {
+        when {
+            // in-place merge to reduce the hierarchy
+            permission is AllOfPermissions -> permissions.addAll(permission.permissions)
+            // allOf(...) and anyOf(p) => allOf(..., p)
+            permission is AnyOfPermissions && permission.permissions.size == 1 ->
+                permissions.add(permission.permissions.first())
+
+            else -> permissions.add(permission)
+        }
+    }
+}
+
+class AnyOfPermissions internal constructor(vararg permissions: Any) : Permissions(*permissions) {
+
+    override fun toString() = permissions.joinToString(prefix = "anyOf(", postfix = ")")
+
+    override fun check(context: Context, pid: Int, uid: Int): Boolean {
+        // use for-loop explicitly instead of "any" extension for empty permissions
+        for (permission in permissions) {
+            if (permission.check(context, pid, uid)) return true
+        }
+        return permissions.isEmpty()
+    }
+
+    internal fun or(permission: Any) {
+        when {
+            // in-place merge to reduce the hierarchy
+            permission is AnyOfPermissions -> permissions.addAll(permission.permissions)
+            // anyOf(...) or allOf(p) => anyOf(..., p)
+            permission is AllOfPermissions && permission.permissions.size == 1 ->
+                permissions.add(permission.permissions.first())
+            else -> permissions.add(permission)
+        }
+    }
+}
+
+infix fun Permissions.and(permission: String): Permissions = addForAnd(permission)
+
+infix fun Permissions.and(permissions: Permissions): Permissions = addForAnd(permissions)
+
+infix fun Permissions.or(permission: String): Permissions = addForOr(permission)
+
+infix fun Permissions.or(permissions: Permissions): Permissions = addForOr(permissions)
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
index 53507fe..614bcb2 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsGlobalStore.kt
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.datastore
 
+import android.Manifest
 import android.content.ContentResolver
 import android.content.Context
 import android.net.Uri
@@ -82,5 +83,11 @@
                             instance = it
                         }
                 }
+
+        /** Returns the required permissions to read [Global] settings. */
+        fun getReadPermissions() = Permissions.EMPTY
+
+        /** Returns the required permissions to write [Global] settings. */
+        fun getWritePermissions() = Permissions.allOf(Manifest.permission.WRITE_SECURE_SETTINGS)
     }
 }
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
index ca7fd7b..2621de1 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSecureStore.kt
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.datastore
 
+import android.Manifest
 import android.content.ContentResolver
 import android.content.Context
 import android.net.Uri
@@ -82,5 +83,11 @@
                             instance = it
                         }
                 }
+
+        /** Returns the required permissions to read [Secure] settings. */
+        fun getReadPermissions() = Permissions.EMPTY
+
+        /** Returns the required permissions to write [Secure] settings. */
+        fun getWritePermissions() = Permissions.allOf(Manifest.permission.WRITE_SECURE_SETTINGS)
     }
 }
diff --git a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
index 20a74d3..740ac39 100644
--- a/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
+++ b/packages/SettingsLib/DataStore/src/com/android/settingslib/datastore/SettingsSystemStore.kt
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.datastore
 
+import android.Manifest
 import android.content.ContentResolver
 import android.content.Context
 import android.net.Uri
@@ -82,5 +83,11 @@
                             instance = it
                         }
                 }
+
+        /** Returns the required permissions to read [System] settings. */
+        fun getReadPermissions() = Permissions.EMPTY
+
+        /** Returns the required permissions to write [System] settings. */
+        fun getWritePermissions() = Permissions.allOf(Manifest.permission.WRITE_SETTINGS)
     }
 }
diff --git a/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/PermissionsTest.kt b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/PermissionsTest.kt
new file mode 100644
index 0000000..5641f0d
--- /dev/null
+++ b/packages/SettingsLib/DataStore/tests/src/com/android/settingslib/datastore/PermissionsTest.kt
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.datastore
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.content.pm.PackageManager.PERMISSION_DENIED
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.datastore.Permissions.Companion.EMPTY
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class PermissionsTest {
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Test
+    fun empty() {
+        assertThat(Permissions.allOf()).isSameInstanceAs(EMPTY)
+        assertThat(Permissions.anyOf()).isSameInstanceAs(EMPTY)
+        assertThat(EMPTY.check(context, 0, 0)).isTrue()
+        assertThat((EMPTY and "a").permissions).containsExactly("a")
+        assertThat((EMPTY or "a").permissions).containsExactly("a")
+    }
+
+    @Test
+    fun allOf_op_empty() {
+        val allOf = Permissions.allOf("a")
+        assertThat(allOf and EMPTY).isSameInstanceAs(allOf)
+        assertThat(EMPTY and allOf).isSameInstanceAs(allOf)
+        assertThat(EMPTY or allOf).isSameInstanceAs(allOf)
+        assertThat(allOf or EMPTY).isSameInstanceAs(allOf)
+    }
+
+    @Test
+    fun anyOf_op_empty() {
+        val anyOf = Permissions.anyOf("a")
+        assertThat(anyOf and EMPTY).isSameInstanceAs(anyOf)
+        assertThat(EMPTY and anyOf).isSameInstanceAs(anyOf)
+        assertThat(EMPTY or anyOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf or EMPTY).isSameInstanceAs(anyOf)
+    }
+
+    @Test
+    fun allOf1_and_allOf1() {
+        val allOf = Permissions.allOf("a")
+        assertThat(allOf and Permissions.allOf("b")).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun allOf1_or_allOf1() {
+        val merged = Permissions.allOf("a") or Permissions.allOf("b")
+        assertThat(merged.permissions).containsExactly("a", "b")
+        assertThat(merged).isInstanceOf(AnyOfPermissions::class.java)
+    }
+
+    @Test
+    fun allOf1_and_anyOf1() {
+        val allOf = Permissions.allOf("a")
+        val anyOf = Permissions.anyOf("b")
+        assertThat(allOf and anyOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun allOf1_or_anyOf1() {
+        val allOf = Permissions.allOf("a")
+        val anyOf = Permissions.anyOf("b")
+        assertThat(allOf or anyOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun anyOf1_and_allOf1() {
+        val anyOf = Permissions.anyOf("a")
+        val allOf = Permissions.allOf("b")
+        assertThat(anyOf and allOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun anyOf1_or_allOf1() {
+        val anyOf = Permissions.anyOf("a")
+        val allOf = Permissions.allOf("b")
+        assertThat(anyOf or allOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun anyOf1_and_anyOf1() {
+        val merged = Permissions.anyOf("a") and Permissions.anyOf("b")
+        assertThat(merged.permissions).containsExactly("a", "b")
+        assertThat(merged).isInstanceOf(AllOfPermissions::class.java)
+    }
+
+    @Test
+    fun anyOf1_or_anyOf1() {
+        val anyOf = Permissions.anyOf("a")
+        assertThat(anyOf or Permissions.anyOf("b")).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b")
+    }
+
+    @Test
+    fun allOf1_and_anyOf2() {
+        val allOf = Permissions.allOf("a")
+        val anyOf = Permissions.anyOf("a", "b")
+        assertThat(allOf and anyOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", anyOf)
+    }
+
+    @Test
+    fun allOf1_or_anyOf2() {
+        val allOf = Permissions.allOf("a")
+        val anyOf = Permissions.anyOf("a", "b")
+        assertThat(allOf and anyOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", anyOf)
+    }
+
+    @Test
+    fun allOf2_and_anyOf1() {
+        val allOf = Permissions.allOf("a", "b")
+        val anyOf = Permissions.anyOf("c")
+        assertThat(allOf and anyOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b", "c")
+    }
+
+    @Test
+    fun allOf2_or_anyOf1() {
+        val allOf = Permissions.allOf("a", "b")
+        val anyOf = Permissions.anyOf("b")
+        assertThat(allOf or anyOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("b", allOf)
+    }
+
+    @Test
+    fun anyOf1_and_allOf2() {
+        val anyOf = Permissions.anyOf("c")
+        val allOf = Permissions.allOf("a", "b")
+        assertThat(anyOf and allOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b", "c")
+    }
+
+    @Test
+    fun anyOf1_or_allOf2() {
+        val anyOf = Permissions.anyOf("a")
+        val allOf = Permissions.allOf("a", "b")
+        assertThat(anyOf or allOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", allOf)
+    }
+
+    @Test
+    fun anyOf2_and_allOf1() {
+        val anyOf = Permissions.anyOf("a", "b")
+        val allOf = Permissions.allOf("a")
+        assertThat(anyOf and allOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", anyOf)
+    }
+
+    @Test
+    fun anyOf2_or_allOf1() {
+        val anyOf = Permissions.anyOf("a", "b")
+        val allOf = Permissions.allOf("c")
+        assertThat(anyOf or allOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b", "c")
+    }
+
+    @Test
+    fun allOf2_and_allOf2() {
+        val allOf = Permissions.allOf("a", "b")
+        assertThat(allOf and Permissions.allOf("a", "c")).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b", "c")
+    }
+
+    @Test
+    fun allOf2_or_allOf2() {
+        val allOf1 = Permissions.allOf("a", "b")
+        val allOf2 = Permissions.allOf("a", "c")
+        assertThat((allOf1 or allOf2).permissions).containsExactly(allOf1, allOf2)
+    }
+
+    @Test
+    fun allOf2_and_anyOf2() {
+        val allOf = Permissions.allOf("a", "b")
+        val anyOf = Permissions.anyOf("a", "c")
+        assertThat(allOf and anyOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "b", anyOf)
+    }
+
+    @Test
+    fun allOf2_or_anyOf2() {
+        val allOf = Permissions.allOf("a", "b")
+        val anyOf = Permissions.anyOf("a", "c")
+        assertThat(allOf or anyOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "c", allOf)
+    }
+
+    @Test
+    fun anyOf2_and_allOf2() {
+        val anyOf = Permissions.anyOf("a", "b")
+        val allOf = Permissions.allOf("a", "c")
+        assertThat(anyOf and allOf).isSameInstanceAs(allOf)
+        assertThat(allOf.permissions).containsExactly("a", "c", anyOf)
+    }
+
+    @Test
+    fun anyOf2_or_allOf2() {
+        val anyOf = Permissions.anyOf("a", "b")
+        val allOf = Permissions.allOf("a", "c")
+        assertThat(anyOf or allOf).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b", allOf)
+    }
+
+    @Test
+    fun anyOf2_and_anyOf2() {
+        val anyOf1 = Permissions.anyOf("a", "b")
+        val anyOf2 = Permissions.anyOf("a", "c")
+        assertThat((anyOf1 and anyOf2).permissions).containsExactly(anyOf1, anyOf2)
+    }
+
+    @Test
+    fun anyOf2_or_anyOf2() {
+        val anyOf = Permissions.anyOf("a", "b")
+        assertThat(anyOf or Permissions.anyOf("a", "c")).isSameInstanceAs(anyOf)
+        assertThat(anyOf.permissions).containsExactly("a", "b", "c")
+    }
+
+    @Test
+    fun check_allOf() {
+        val permissions = Permissions.allOf("a", "b")
+        assertThat(permissions.check(PermissionsContext(setOf()), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("b")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b")), 0, 0)).isTrue()
+    }
+
+    @Test
+    fun check_allOf_mixed() {
+        val permissions = Permissions.allOf("a", "b") or "c"
+        assertThat(permissions.permissions).hasSize(2)
+        assertThat(permissions.check(PermissionsContext(setOf()), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("b")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("c")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "c")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("b", "c")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b", "c")), 0, 0)).isTrue()
+    }
+
+    @Test
+    fun check_anyOf() {
+        val permissions = Permissions.anyOf("a", "b")
+        assertThat(permissions.check(PermissionsContext(setOf()), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("b")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b")), 0, 0)).isTrue()
+    }
+
+    @Test
+    fun check_anyOf_mixed() {
+        val permissions = Permissions.anyOf("a", "b") and "c"
+        assertThat(permissions.permissions).hasSize(2)
+        assertThat(permissions.check(PermissionsContext(setOf()), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("b")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("c")), 0, 0)).isFalse()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "c")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("b", "c")), 0, 0)).isTrue()
+        assertThat(permissions.check(PermissionsContext(setOf("a", "b", "c")), 0, 0)).isTrue()
+    }
+
+    @Test
+    fun equals() {
+        assertThat(Permissions.allOf("a")).isEqualTo(Permissions.allOf("a"))
+        assertThat(Permissions.allOf("a")).isEqualTo(Permissions.anyOf("a"))
+        assertThat(Permissions.anyOf("a")).isEqualTo(Permissions.allOf("a"))
+        assertThat(Permissions.anyOf("a")).isEqualTo(Permissions.anyOf("a"))
+
+        assertThat(Permissions.anyOf("a") and "b").isEqualTo(Permissions.allOf("a", "b"))
+        assertThat(Permissions.allOf("a") or "b").isEqualTo(Permissions.anyOf("a", "b"))
+        assertThat(Permissions.allOf("a") and "a").isEqualTo(Permissions.allOf("a"))
+        assertThat(Permissions.anyOf("a") or "a").isEqualTo(Permissions.anyOf("a"))
+
+        assertThat(Permissions.allOf("a", "c") and Permissions.allOf("c", "b"))
+            .isEqualTo(Permissions.allOf("a", "b", "c"))
+        assertThat(Permissions.anyOf("a", "c") or Permissions.anyOf("c", "b"))
+            .isEqualTo(Permissions.anyOf("a", "b", "c"))
+
+        assertThat(Permissions.allOf("a", "c") and Permissions.allOf("c", "b"))
+            .isEqualTo(Permissions.allOf("b", "c") and Permissions.allOf("c", "a"))
+        assertThat(Permissions.anyOf("a", "c") or Permissions.anyOf("c", "b"))
+            .isEqualTo(Permissions.anyOf("b", "c") or Permissions.anyOf("c", "a"))
+    }
+
+    @Test
+    fun notEquals() {
+        assertThat(Permissions.allOf("a")).isNotEqualTo(Permissions.allOf("a", "b"))
+        assertThat(Permissions.anyOf("a")).isNotEqualTo(Permissions.anyOf("a", "b"))
+        assertThat(Permissions.allOf("a", "b")).isNotEqualTo(Permissions.anyOf("a", "b"))
+    }
+}
+
+private class PermissionsContext(private val granted: Set<String>) :
+    ContextWrapper(ApplicationProvider.getApplicationContext()) {
+
+    override fun checkPermission(permission: String, pid: Int, uid: Int) =
+        if (permission in granted) PERMISSION_GRANTED else PERMISSION_DENIED
+}
diff --git a/packages/SettingsLib/Graph/graph.proto b/packages/SettingsLib/Graph/graph.proto
index f611793..33a7df4 100644
--- a/packages/SettingsLib/Graph/graph.proto
+++ b/packages/SettingsLib/Graph/graph.proto
@@ -81,6 +81,10 @@
   optional PreferenceValueDescriptorProto value_descriptor = 15;
   // Indicate how sensitive of the preference.
   optional int32 sensitivity_level = 16;
+  // The required permissions to read preference value.
+  optional PermissionsProto read_permissions = 17;
+  // The required permissions to write preference value.
+  optional PermissionsProto write_permissions = 18;
 
   // Target of an Intent
   message ActionTarget {
@@ -95,6 +99,20 @@
   }
 }
 
+// Proto of permissions
+message PermissionsProto {
+  repeated PermissionProto all_of = 1;
+  repeated PermissionProto any_of = 2;
+}
+
+// Proto of permission
+message PermissionProto {
+  oneof kind {
+    string permission = 1;
+    PermissionsProto permissions = 2;
+  }
+}
+
 // Proto of string or string resource id.
 message TextProto {
   oneof text {
@@ -108,6 +126,7 @@
   oneof value {
     bool boolean_value = 1;
     int32 int_value = 2;
+    float float_value = 3;
   }
 }
 
@@ -116,6 +135,7 @@
   oneof type {
     bool boolean_type = 1;
     RangeValueProto range_value = 2;
+    bool float_type = 3;
   }
 }
 
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PermissionsProtos.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PermissionsProtos.kt
new file mode 100644
index 0000000..5971b42
--- /dev/null
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PermissionsProtos.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.graph
+
+import com.android.settingslib.datastore.AllOfPermissions
+import com.android.settingslib.datastore.AnyOfPermissions
+import com.android.settingslib.datastore.Permissions
+import com.android.settingslib.datastore.and
+import com.android.settingslib.datastore.or
+import com.android.settingslib.graph.proto.PermissionProto
+import com.android.settingslib.graph.proto.PermissionsProto
+
+inline fun permissionsProto(init: PermissionsProto.Builder.() -> Unit): PermissionsProto =
+    PermissionsProto.newBuilder().also(init).build()
+
+inline fun permissionProto(init: PermissionProto.Builder.() -> Unit): PermissionProto =
+    PermissionProto.newBuilder().also(init).build()
+
+fun Permissions.toProto(): PermissionsProto = permissionsProto {
+    when (this@toProto) {
+        is AllOfPermissions -> {
+            forEach { addAllOf(it.toPermissionProto()) }
+        }
+        is AnyOfPermissions -> {
+            forEach { addAnyOf(it.toPermissionProto()) }
+        }
+    }
+}
+
+private fun Any.toPermissionProto() =
+    when {
+        this is Permissions -> permissionProto { permissions = toProto() }
+        else -> permissionProto { permission = this@toPermissionProto as String }
+    }
+
+fun PermissionsProto.getAllPermissions(): List<String> {
+    val permissions = mutableSetOf<String>()
+    fun Permissions.collect() {
+        forEach {
+            when {
+                it is String -> permissions.add(it)
+                else -> (it as Permissions).collect()
+            }
+        }
+    }
+    toPermissions().collect()
+    return permissions.toList()
+}
+
+fun PermissionsProto.toPermissions(): Permissions {
+    var permissions = Permissions.EMPTY
+    for (index in 0 until allOfCount) {
+        val permission = getAllOf(index).toPermission()
+        permissions =
+            when (permission) {
+                is String -> permissions and permission
+                else -> permissions and (permission as Permissions)
+            }
+    }
+    for (index in 0 until anyOfCount) {
+        val permission = getAnyOf(index).toPermission()
+        permissions =
+            when (permission) {
+                is String -> permissions or permission
+                else -> permissions or (permission as Permissions)
+            }
+    }
+    return permissions
+}
+
+private fun PermissionProto.toPermission(): Any =
+    when {
+        hasPermissions() -> permissions.toPermissions()
+        else -> permission
+    }
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
index eaa7926..2cf32de 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
@@ -22,7 +22,6 @@
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
-import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.content.res.Configuration
 import android.os.Build
 import android.os.Bundle
@@ -42,6 +41,7 @@
 import com.android.settingslib.graph.proto.PreferenceScreenProto
 import com.android.settingslib.graph.proto.TextProto
 import com.android.settingslib.metadata.BooleanValue
+import com.android.settingslib.metadata.FloatPersistentPreference
 import com.android.settingslib.metadata.PersistentPreference
 import com.android.settingslib.metadata.PreferenceAvailabilityProvider
 import com.android.settingslib.metadata.PreferenceHierarchy
@@ -390,7 +390,15 @@
     }
     persistent = metadata.isPersistent(context)
     if (persistent) {
-        if (metadata is PersistentPreference<*>) sensitivityLevel = metadata.sensitivityLevel
+        if (metadata is PersistentPreference<*>) {
+            sensitivityLevel = metadata.sensitivityLevel
+            metadata.getReadPermissions(context)?.let {
+                if (it.size > 0) readPermissions = it.toProto()
+            }
+            metadata.getWritePermissions(context)?.let {
+                if (it.size > 0) writePermissions = it.toProto()
+            }
+        }
         if (
             flags.includeValue() &&
                 enabled &&
@@ -399,15 +407,13 @@
                 metadata is PersistentPreference<*> &&
                 metadata.evalReadPermit(context, callingPid, callingUid) == ReadWritePermit.ALLOW
         ) {
+            val storage = metadata.storage(context)
             value = preferenceValueProto {
                 when (metadata) {
-                    is BooleanValue ->
-                        metadata.storage(context).getBoolean(metadata.key)?.let {
-                            booleanValue = it
-                        }
-                    is RangeValue -> {
-                        metadata.storage(context).getInt(metadata.key)?.let { intValue = it }
-                    }
+                    is BooleanValue -> storage.getBoolean(metadata.key)?.let { booleanValue = it }
+                    is RangeValue -> storage.getInt(metadata.key)?.let { intValue = it }
+                    is FloatPersistentPreference ->
+                        storage.getFloat(metadata.key)?.let { floatValue = it }
                     else -> {}
                 }
             }
@@ -421,6 +427,7 @@
                             max = metadata.getMaxValue(context)
                             step = metadata.getIncrementStep(context)
                         }
+                    is FloatPersistentPreference -> floatType = true
                     else -> {}
                 }
             }
@@ -433,14 +440,12 @@
     context: Context,
     callingPid: Int,
     callingUid: Int,
-): Int {
-    for (permission in getReadPermissions(context)) {
-        if (context.checkPermission(permission, callingPid, callingUid) != PERMISSION_GRANTED) {
-            return ReadWritePermit.REQUIRE_APP_PERMISSION
-        }
+): Int =
+    when {
+        getReadPermissions(context)?.check(context, callingPid, callingUid) == false ->
+            ReadWritePermit.REQUIRE_APP_PERMISSION
+        else -> getReadPermit(context, callingPid, callingUid)
     }
-    return getReadPermit(context, callingPid, callingUid)
-}
 
 private fun PreferenceMetadata.getTitleTextProto(context: Context, isRoot: Boolean): TextProto? {
     if (isRoot && this is PreferenceScreenMetadata) {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
index d72ba08..bef4bb2 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
@@ -18,7 +18,6 @@
 
 import android.app.Application
 import android.content.Context
-import android.content.pm.PackageManager.PERMISSION_GRANTED
 import android.os.Bundle
 import androidx.annotation.IntDef
 import com.android.settingslib.graph.proto.PreferenceValueProto
@@ -159,6 +158,12 @@
                 }
                 storage.setInt(key, intValue)
                 return PreferenceSetterResult.OK
+            } else if (value.hasFloatValue()) {
+                val floatValue = value.floatValue
+                val resultCode = metadata.checkWritePermit(floatValue)
+                if (resultCode != PreferenceSetterResult.OK) return resultCode
+                storage.setFloat(key, floatValue)
+                return PreferenceSetterResult.OK
             }
         } catch (e: Exception) {
             return PreferenceSetterResult.INTERNAL_ERROR
@@ -179,14 +184,12 @@
     value: T?,
     callingPid: Int,
     callingUid: Int,
-): Int {
-    for (permission in getWritePermissions(context)) {
-        if (context.checkPermission(permission, callingPid, callingUid) != PERMISSION_GRANTED) {
-            return ReadWritePermit.REQUIRE_APP_PERMISSION
-        }
+): Int =
+    when {
+        getWritePermissions(context)?.check(context, callingPid, callingUid) == false ->
+            ReadWritePermit.REQUIRE_APP_PERMISSION
+        else -> getWritePermit(context, value, callingPid, callingUid)
     }
-    return getWritePermit(context, value, callingPid, callingUid)
-}
 
 /** Message codec for [PreferenceSetterRequest]. */
 object PreferenceSetterRequestCodec : MessageCodec<PreferenceSetterRequest> {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
index dee32d9..adbe773 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
@@ -35,8 +35,9 @@
 
 /** Kotlin DSL-style builder for [PreferenceScreenProto]. */
 @JvmSynthetic
-inline fun preferenceScreenProto(init: PreferenceScreenProto.Builder.() -> Unit) =
-    PreferenceScreenProto.newBuilder().also(init).build()
+inline fun preferenceScreenProto(
+    init: PreferenceScreenProto.Builder.() -> Unit
+): PreferenceScreenProto = PreferenceScreenProto.newBuilder().also(init).build()
 
 /** Returns preference or null. */
 val PreferenceOrGroupProto.preferenceOrNull
@@ -48,8 +49,9 @@
 
 /** Kotlin DSL-style builder for [PreferenceOrGroupProto]. */
 @JvmSynthetic
-inline fun preferenceOrGroupProto(init: PreferenceOrGroupProto.Builder.() -> Unit) =
-    PreferenceOrGroupProto.newBuilder().also(init).build()
+inline fun preferenceOrGroupProto(
+    init: PreferenceOrGroupProto.Builder.() -> Unit
+): PreferenceOrGroupProto = PreferenceOrGroupProto.newBuilder().also(init).build()
 
 /** Returns preference or null. */
 val PreferenceGroupProto.preferenceOrNull
@@ -57,8 +59,9 @@
 
 /** Kotlin DSL-style builder for [PreferenceGroupProto]. */
 @JvmSynthetic
-inline fun preferenceGroupProto(init: PreferenceGroupProto.Builder.() -> Unit) =
-    PreferenceGroupProto.newBuilder().also(init).build()
+inline fun preferenceGroupProto(
+    init: PreferenceGroupProto.Builder.() -> Unit
+): PreferenceGroupProto = PreferenceGroupProto.newBuilder().also(init).build()
 
 /** Returns title or null. */
 val PreferenceProto.titleOrNull
@@ -74,7 +77,7 @@
 
 /** Kotlin DSL-style builder for [PreferenceProto]. */
 @JvmSynthetic
-inline fun preferenceProto(init: PreferenceProto.Builder.() -> Unit) =
+inline fun preferenceProto(init: PreferenceProto.Builder.() -> Unit): PreferenceProto =
     PreferenceProto.newBuilder().also(init).build()
 
 /** Returns intent or null. */
@@ -83,39 +86,42 @@
 
 /** Kotlin DSL-style builder for [ActionTarget]. */
 @JvmSynthetic
-inline fun actionTargetProto(init: ActionTarget.Builder.() -> Unit) =
+inline fun actionTargetProto(init: ActionTarget.Builder.() -> Unit): ActionTarget =
     ActionTarget.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [PreferenceValueProto]. */
 @JvmSynthetic
-inline fun preferenceValueProto(init: PreferenceValueProto.Builder.() -> Unit) =
-    PreferenceValueProto.newBuilder().also(init).build()
+inline fun preferenceValueProto(
+    init: PreferenceValueProto.Builder.() -> Unit
+): PreferenceValueProto = PreferenceValueProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [PreferenceValueDescriptorProto]. */
 @JvmSynthetic
-inline fun preferenceValueDescriptorProto(init: PreferenceValueDescriptorProto.Builder.() -> Unit) =
-    PreferenceValueDescriptorProto.newBuilder().also(init).build()
+inline fun preferenceValueDescriptorProto(
+    init: PreferenceValueDescriptorProto.Builder.() -> Unit
+): PreferenceValueDescriptorProto = PreferenceValueDescriptorProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [RangeValueProto]. */
 @JvmSynthetic
-inline fun rangeValueProto(init: RangeValueProto.Builder.() -> Unit) =
+inline fun rangeValueProto(init: RangeValueProto.Builder.() -> Unit): RangeValueProto =
     RangeValueProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [TextProto]. */
 @JvmSynthetic
-inline fun textProto(init: TextProto.Builder.() -> Unit) = TextProto.newBuilder().also(init).build()
+inline fun textProto(init: TextProto.Builder.() -> Unit): TextProto =
+    TextProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [IntentProto]. */
 @JvmSynthetic
-inline fun intentProto(init: IntentProto.Builder.() -> Unit) =
+inline fun intentProto(init: IntentProto.Builder.() -> Unit): IntentProto =
     IntentProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [BundleProto]. */
 @JvmSynthetic
-inline fun bundleProto(init: BundleProto.Builder.() -> Unit) =
+inline fun bundleProto(init: BundleProto.Builder.() -> Unit): BundleProto =
     BundleProto.newBuilder().also(init).build()
 
 /** Kotlin DSL-style builder for [BundleValue]. */
 @JvmSynthetic
-inline fun bundleValueProto(init: BundleValue.Builder.() -> Unit) =
+inline fun bundleValueProto(init: BundleValue.Builder.() -> Unit): BundleValue =
     BundleValue.newBuilder().also(init).build()
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index adc4f316..bc4f1f9 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -167,6 +167,7 @@
         if (mLottieDynamicColor) {
             LottieColorUtils.applyDynamicColors(getContext(), illustrationView);
         }
+        LottieColorUtils.applyMaterialColor(getContext(), illustrationView);
 
         if (mOnBindListener != null) {
             mOnBindListener.onBind(illustrationView);
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java
index 98a7290..4421424 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java
@@ -21,14 +21,14 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 
-import com.android.settingslib.color.R;
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.widget.theme.R;
 
 import com.airbnb.lottie.LottieAnimationView;
 import com.airbnb.lottie.LottieProperty;
 import com.airbnb.lottie.model.KeyPath;
 
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -37,52 +37,97 @@
  */
 public class LottieColorUtils {
     private static final Map<String, Integer> DARK_TO_LIGHT_THEME_COLOR_MAP;
+    private static final Map<String, Integer> MATERIAL_COLOR_MAP;
 
     static {
-        HashMap<String, Integer> map = new HashMap<>();
-        map.put(
-                ".grey200",
-                R.color.settingslib_color_grey800);
-        map.put(
-                ".grey600",
-                R.color.settingslib_color_grey400);
-        map.put(
-                ".grey800",
-                R.color.settingslib_color_grey300);
-        map.put(
-                ".grey900",
-                R.color.settingslib_color_grey50);
-        map.put(
-                ".red100",
-                R.color.settingslib_color_red500);
-        map.put(
-                ".red200",
-                R.color.settingslib_color_red500);
-        map.put(
-                ".red400",
-                R.color.settingslib_color_red600);
-        map.put(
-                ".black",
-                android.R.color.white);
-        map.put(
-                ".blue200",
-                R.color.settingslib_color_blue700);
-        map.put(
-                ".blue400",
-                R.color.settingslib_color_blue600);
-        map.put(
-                ".green100",
-                R.color.settingslib_color_green500);
-        map.put(
-                ".green200",
-                R.color.settingslib_color_green500);
-        map.put(
-                ".green400",
-                R.color.settingslib_color_green600);
-        map.put(
-                ".cream",
-                R.color.settingslib_color_charcoal);
-        DARK_TO_LIGHT_THEME_COLOR_MAP = Collections.unmodifiableMap(map);
+        DARK_TO_LIGHT_THEME_COLOR_MAP = Map.ofEntries(
+                Map.entry(".grey200",
+                        com.android.settingslib.color.R.color.settingslib_color_grey800),
+                Map.entry(".grey600",
+                        com.android.settingslib.color.R.color.settingslib_color_grey400),
+                Map.entry(".grey800",
+                        com.android.settingslib.color.R.color.settingslib_color_grey300),
+                Map.entry(".grey900",
+                        com.android.settingslib.color.R.color.settingslib_color_grey50),
+                Map.entry(".red100",
+                        com.android.settingslib.color.R.color.settingslib_color_red500),
+                Map.entry(".red200",
+                        com.android.settingslib.color.R.color.settingslib_color_red500),
+                Map.entry(".red400",
+                        com.android.settingslib.color.R.color.settingslib_color_red600),
+                Map.entry(".black",
+                        android.R.color.white),
+                Map.entry(".blue200",
+                        com.android.settingslib.color.R.color.settingslib_color_blue700),
+                Map.entry(".blue400",
+                        com.android.settingslib.color.R.color.settingslib_color_blue600),
+                Map.entry(".green100",
+                        com.android.settingslib.color.R.color.settingslib_color_green500),
+                Map.entry(".green200",
+                        com.android.settingslib.color.R.color.settingslib_color_green500),
+                Map.entry(".green400",
+                        com.android.settingslib.color.R.color.settingslib_color_green600),
+                Map.entry(".cream",
+                        com.android.settingslib.color.R.color.settingslib_color_charcoal));
+
+        MATERIAL_COLOR_MAP = Map.ofEntries(
+                Map.entry(".primary", R.color.settingslib_materialColorPrimary),
+                Map.entry(".onPrimary", R.color.settingslib_materialColorOnPrimary),
+                Map.entry(".primaryContainer", R.color.settingslib_materialColorPrimaryContainer),
+                Map.entry(".onPrimaryContainer",
+                        R.color.settingslib_materialColorOnPrimaryContainer),
+                Map.entry(".primaryInverse", R.color.settingslib_materialColorPrimaryInverse),
+                Map.entry(".primaryFixed", R.color.settingslib_materialColorPrimaryFixed),
+                Map.entry(".primaryFixedDim", R.color.settingslib_materialColorPrimaryFixedDim),
+                Map.entry(".onPrimaryFixed", R.color.settingslib_materialColorOnPrimaryFixed),
+                Map.entry(".onPrimaryFixedVariant",
+                        R.color.settingslib_materialColorOnPrimaryFixedVariant),
+                Map.entry(".secondary", R.color.settingslib_materialColorSecondary),
+                Map.entry(".onSecondary", R.color.settingslib_materialColorOnSecondary),
+                Map.entry(".secondaryContainer",
+                        R.color.settingslib_materialColorSecondaryContainer),
+                Map.entry(".onSecondaryContainer",
+                        R.color.settingslib_materialColorOnSecondaryContainer),
+                Map.entry(".secondaryFixed", R.color.settingslib_materialColorSecondaryFixed),
+                Map.entry(".secondaryFixedDim", R.color.settingslib_materialColorSecondaryFixedDim),
+                Map.entry(".onSecondaryFixed", R.color.settingslib_materialColorOnSecondaryFixed),
+                Map.entry(".onSecondaryFixedVariant",
+                        R.color.settingslib_materialColorOnSecondaryFixedVariant),
+                Map.entry(".tertiary", R.color.settingslib_materialColorTertiary),
+                Map.entry(".onTertiary", R.color.settingslib_materialColorOnTertiary),
+                Map.entry(".tertiaryContainer", R.color.settingslib_materialColorTertiaryContainer),
+                Map.entry(".onTertiaryContainer",
+                        R.color.settingslib_materialColorOnTertiaryContainer),
+                Map.entry(".tertiaryFixed", R.color.settingslib_materialColorTertiaryFixed),
+                Map.entry(".tertiaryFixedDim", R.color.settingslib_materialColorTertiaryFixedDim),
+                Map.entry(".onTertiaryFixed", R.color.settingslib_materialColorOnTertiaryFixed),
+                Map.entry(".onTertiaryFixedVariant",
+                        R.color.settingslib_materialColorOnTertiaryFixedVariant),
+                Map.entry(".error", R.color.settingslib_materialColorError),
+                Map.entry(".onError", R.color.settingslib_materialColorOnError),
+                Map.entry(".errorContainer", R.color.settingslib_materialColorErrorContainer),
+                Map.entry(".onErrorContainer", R.color.settingslib_materialColorOnErrorContainer),
+                Map.entry(".outline", R.color.settingslib_materialColorOutline),
+                Map.entry(".outlineVariant", R.color.settingslib_materialColorOutlineVariant),
+                Map.entry(".background", R.color.settingslib_materialColorBackground),
+                Map.entry(".onBackground", R.color.settingslib_materialColorOnBackground),
+                Map.entry(".surface", R.color.settingslib_materialColorSurface),
+                Map.entry(".onSurface", R.color.settingslib_materialColorOnSurface),
+                Map.entry(".surfaceVariant", R.color.settingslib_materialColorSurfaceVariant),
+                Map.entry(".onSurfaceVariant", R.color.settingslib_materialColorOnSurfaceVariant),
+                Map.entry(".surfaceInverse", R.color.settingslib_materialColorSurfaceInverse),
+                Map.entry(".onSurfaceInverse", R.color.settingslib_materialColorOnSurfaceInverse),
+                Map.entry(".surfaceBright", R.color.settingslib_materialColorSurfaceBright),
+                Map.entry(".surfaceDim", R.color.settingslib_materialColorSurfaceDim),
+                Map.entry(".surfaceContainer", R.color.settingslib_materialColorSurfaceContainer),
+                Map.entry(".surfaceContainerLow",
+                        R.color.settingslib_materialColorSurfaceContainerLow),
+                Map.entry(".surfaceContainerLowest",
+                        R.color.settingslib_materialColorSurfaceContainerLowest),
+                Map.entry(".surfaceContainerHigh",
+                        R.color.settingslib_materialColorSurfaceContainerHigh),
+                Map.entry(".surfaceContainerHighest",
+                        R.color.settingslib_materialColorSurfaceContainerHighest));
     }
 
     private LottieColorUtils() {
@@ -108,4 +153,20 @@
                     frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
         }
     }
+
+    /** Applies material colors. */
+    public static void applyMaterialColor(@NonNull Context context,
+            @NonNull LottieAnimationView lottieAnimationView) {
+        if (!SettingsThemeHelper.isExpressiveTheme(context)) {
+            return;
+        }
+
+        for (String key : MATERIAL_COLOR_MAP.keySet()) {
+            final int color = context.getColor(MATERIAL_COLOR_MAP.get(key));
+            lottieAnimationView.addValueCallback(
+                    new KeyPath("**", key, "**"),
+                    LottieProperty.COLOR_FILTER,
+                    frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP));
+        }
+    }
 }
diff --git a/packages/SettingsLib/LayoutPreference/src/com/android/settingslib/widget/LayoutPreference.java b/packages/SettingsLib/LayoutPreference/src/com/android/settingslib/widget/LayoutPreference.java
index 49f045f..5df617c 100644
--- a/packages/SettingsLib/LayoutPreference/src/com/android/settingslib/widget/LayoutPreference.java
+++ b/packages/SettingsLib/LayoutPreference/src/com/android/settingslib/widget/LayoutPreference.java
@@ -41,7 +41,7 @@
  *      xxxxxxx:allowDividerBelow="true"
  *
  */
-public class LayoutPreference extends Preference {
+public class LayoutPreference extends Preference implements GroupSectionDividerMixin {
 
     private final View.OnClickListener mClickListener = v -> performClick(v);
     private boolean mAllowDividerAbove;
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
index d3a7316..e5bf41f 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PersistentPreference.kt
@@ -20,6 +20,7 @@
 import androidx.annotation.ArrayRes
 import androidx.annotation.IntDef
 import com.android.settingslib.datastore.KeyValueStore
+import com.android.settingslib.datastore.Permissions
 
 /** Permit of read and write request. */
 @IntDef(
@@ -69,7 +70,7 @@
         PreferenceScreenRegistry.getKeyValueStore(context, this as PreferenceMetadata)!!
 
     /** Returns the required permissions to read preference value. */
-    fun getReadPermissions(context: Context): Array<String> = arrayOf()
+    fun getReadPermissions(context: Context): Permissions? = null
 
     /**
      * Returns if the external application (identified by [callingPid] and [callingUid]) is
@@ -88,7 +89,7 @@
         )
 
     /** Returns the required permissions to write preference value. */
-    fun getWritePermissions(context: Context): Array<String> = arrayOf()
+    fun getWritePermissions(context: Context): Permissions? = null
 
     /**
      * Returns if the external application (identified by [callingPid] and [callingUid]) is
@@ -201,3 +202,6 @@
     override fun isValidValue(context: Context, index: Int) =
         index in getMinValue(context)..getMaxValue(context)
 }
+
+/** A persistent preference that has a float value. */
+interface FloatPersistentPreference : PersistentPreference<Float>
diff --git a/packages/SettingsLib/Preference/testutils/com/android/settingslib/preference/PreferenceBindingTestUtils.kt b/packages/SettingsLib/Preference/testutils/com/android/settingslib/preference/PreferenceBindingTestUtils.kt
index 00bad52..220614b 100644
--- a/packages/SettingsLib/Preference/testutils/com/android/settingslib/preference/PreferenceBindingTestUtils.kt
+++ b/packages/SettingsLib/Preference/testutils/com/android/settingslib/preference/PreferenceBindingTestUtils.kt
@@ -19,18 +19,27 @@
 import android.content.Context
 import androidx.annotation.VisibleForTesting
 import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
 import com.android.settingslib.metadata.PersistentPreference
 import com.android.settingslib.metadata.PreferenceMetadata
 
 /** Creates [Preference] widget and binds with metadata. */
+@Suppress("UNCHECKED_CAST")
 @VisibleForTesting
-fun <P : Preference> PreferenceMetadata.createAndBindWidget(context: Context): P {
+fun <P : Preference> PreferenceMetadata.createAndBindWidget(
+    context: Context,
+    preferenceScreen: PreferenceScreen? = null,
+): P {
     val binding = PreferenceBindingFactory.defaultFactory.getPreferenceBinding(this)!!
     return (binding.createWidget(context) as P).also {
         if (this is PersistentPreference<*>) {
-            storage(context)?.let { keyValueStore ->
+            storage(context).let { keyValueStore ->
                 it.preferenceDataStore = PreferenceDataStoreAdapter(keyValueStore)
             }
+            // Attach preference to preference screen, otherwise `Preference.performClick` does not
+            // interact with underlying datastore
+            (preferenceScreen ?: PreferenceScreenFactory(context).getOrCreatePreferenceScreen())
+                .addPreference(it)
         }
         binding.bind(it, this)
     }
diff --git a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
index 03a2101..218983a 100644
--- a/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
+++ b/packages/SettingsLib/SelectorWithWidgetPreference/src/com/android/settingslib/widget/SelectorWithWidgetPreference.java
@@ -31,7 +31,6 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settingslib.widget.preference.selector.R;
-import com.android.settingslib.widget.selectorwithwidgetpreference.flags.Flags;
 
 /**
  * Selector preference (checkbox or radio button) with an optional additional widget.
@@ -180,10 +179,8 @@
                     : getContext().getString(R.string.settings_label));
         }
 
-        if (Flags.allowSetTitleMaxLines()) {
-            TextView title = (TextView) holder.findViewById(android.R.id.title);
-            title.setMaxLines(mTitleMaxLines);
-        }
+        TextView title = (TextView) holder.findViewById(android.R.id.title);
+        title.setMaxLines(mTitleMaxLines);
     }
 
     /**
@@ -244,16 +241,12 @@
         setLayoutResource(R.layout.preference_selector_with_widget);
         setIconSpaceReserved(false);
 
-        if (Flags.allowSetTitleMaxLines()) {
-            final TypedArray a =
-                    context.obtainStyledAttributes(
-                            attrs, R.styleable.SelectorWithWidgetPreference, defStyleAttr,
-                            defStyleRes);
-            mTitleMaxLines =
-                    a.getInt(R.styleable.SelectorWithWidgetPreference_titleMaxLines,
-                            DEFAULT_MAX_LINES);
-            a.recycle();
-        }
+        final TypedArray a =
+                context.obtainStyledAttributes(
+                        attrs, R.styleable.SelectorWithWidgetPreference, defStyleAttr, defStyleRes);
+        mTitleMaxLines =
+                a.getInt(R.styleable.SelectorWithWidgetPreference_titleMaxLines, DEFAULT_MAX_LINES);
+        a.recycle();
     }
 
     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
diff --git a/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outline_color_selector.xml b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outline_color_selector.xml
new file mode 100644
index 0000000..5084f11
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outline_color_selector.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:color="@android:color/transparent"/>
+    <item android:color="?attr/colorOutlineVariant"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outlined_background_color_selector.xml b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outlined_background_color_selector.xml
new file mode 100644
index 0000000..ed05cdd
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_button_outlined_background_color_selector.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:state_checked="true"
+        android:alpha="0.12"
+        android:color="?attr/colorOnSurface"/>
+    <item android:state_checked="true" android:color="?attr/colorContainerChecked"/>
+    <item android:state_checkable="true" android:color="?attr/colorContainerUnchecked"/>
+    <item android:color="?attr/colorContainer" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_filled_button_color.xml b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_filled_button_color.xml
new file mode 100644
index 0000000..678bec4
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/color/settingslib_expressive_filled_button_color.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:alpha="0.12" android:color="@color/settingslib_materialColorOnSurface"/>
+    <item android:state_checked="true" android:color="@color/settingslib_materialColorPrimary"/>
+    <item android:state_checkable="true" android:color="@color/settingslib_materialColorSurfaceContainer"/>
+    <item android:color="@color/settingslib_materialColorPrimary" />
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
index 2261e58..2776544 100644
--- a/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
+++ b/packages/SettingsLib/SettingsTheme/res/layout-v35/settingslib_expressive_collapsable_textview.xml
@@ -57,6 +57,7 @@
         android:id="@+id/collapse_button"
         app:layout_constraintTop_toBottomOf="@id/settingslib_expressive_learn_more"
         app:layout_constraintStart_toStartOf="parent"
+        android:textColor="@color/settingslib_materialColorOnSurface"
         android:text="@string/settingslib_expressive_text_expand"
         app:icon="@drawable/settingslib_expressive_icon_expand"
         style="@style/SettingslibTextButtonStyle.Expressive"/>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles_expressive.xml
index 9d3d70b..b5f22b7 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles_expressive.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles_expressive.xml
@@ -17,27 +17,16 @@
 
 <resources>
     <style name="SettingsLibButtonStyle.Expressive.Filled"
-        parent="@style/Widget.Material3.Button">
+        parent="@style/Widget.Material3Expressive.Button.Icon">
         <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:gravity">center</item>
-        <item name="android:minWidth">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:minHeight">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_extrasmall5</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small1</item>
-        <item name="android:backgroundTint">@color/settingslib_materialColorPrimary</item>
         <item name="android:textAppearance">@style/TextAppearance.SettingsLib.LabelLarge</item>
-        <item name="android:textColor">@color/settingslib_materialColorOnPrimary</item>
-        <item name="iconGravity">textStart</item>
-        <item name="iconTint">@color/settingslib_materialColorOnPrimary</item>
-        <item name="iconSize">@dimen/settingslib_expressive_space_small4</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Filled.Large">
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_small1</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small4</item>
-        <item name="android:textAppearance">@style/TextAppearance.SettingsLib.TitleMedium</item>
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Medium</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Filled.Extra"
@@ -45,28 +34,34 @@
         <item name="android:layout_width">match_parent</item>
     </style>
 
-    <style name="SettingsLibButtonStyle.Expressive.Tonal"
-        parent="@style/Widget.Material3.Button.TonalButton">
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Filled"
+        parent="@style/Widget.Material3Expressive.Button.IconButton.Filled">
         <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:gravity">center</item>
-        <item name="android:minWidth">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:minHeight">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_extrasmall5</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small1</item>
-        <item name="android:backgroundTint">@color/settingslib_materialColorSecondaryContainer</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Filled.Large">
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Medium</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Filled.Extra"
+        parent="@style/SettingsLibButtonStyle.Expressive.Icon.Filled.Large">
+        <item name="android:layout_width">match_parent</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Tonal"
+        parent="@style/Widget.Material3Expressive.Button.TonalButton.Icon">
+        <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">center</item>
         <item name="android:textAppearance">@style/TextAppearance.SettingsLib.LabelLarge</item>
-        <item name="android:textColor">@color/settingslib_materialColorOnSecondaryContainer</item>
-        <item name="iconGravity">textStart</item>
-        <item name="iconTint">@color/settingslib_materialColorOnSecondaryContainer</item>
-        <item name="iconSize">@dimen/settingslib_expressive_space_small4</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Tonal.Large">
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_small1</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small4</item>
-        <item name="android:textAppearance">@style/TextAppearance.SettingsLib.TitleMedium</item>
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Medium</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Tonal.Extra"
@@ -74,29 +69,34 @@
         <item name="android:layout_width">match_parent</item>
     </style>
 
-    <style name="SettingsLibButtonStyle.Expressive.Outline"
-        parent="@style/Widget.Material3.Button.OutlinedButton.Icon">
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Tonal"
+        parent="@style/Widget.Material3Expressive.Button.IconButton.Tonal">
         <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:gravity">center</item>
-        <item name="android:minWidth">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:minHeight">@dimen/settingslib_expressive_space_medium4</item>
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_extrasmall5</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small1</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Tonal.Large">
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Medium</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Icon.Tonal.Extra"
+        parent="@style/SettingsLibButtonStyle.Expressive.Tonal.Large">
+        <item name="android:layout_width">match_parent</item>
+    </style>
+
+    <style name="SettingsLibButtonStyle.Expressive.Outline"
+        parent="@style/Widget.Material3Expressive.Button.OutlinedButton.Icon">
+        <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:gravity">center</item>
         <item name="android:textAppearance">@style/TextAppearance.SettingsLib.LabelLarge</item>
-        <item name="android:textColor">@color/settingslib_materialColorPrimary</item>
-        <item name="iconTint">@color/settingslib_materialColorPrimary</item>
-        <item name="iconGravity">textStart</item>
-        <item name="iconSize">@dimen/settingslib_expressive_space_small4</item>
-        <item name="iconPadding">@dimen/settingslib_expressive_space_extrasmall4</item>
-        <item name="strokeColor">@color/settingslib_materialColorOutlineVariant</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Outline.Large">
-        <item name="android:paddingVertical">@dimen/settingslib_expressive_space_small1</item>
-        <item name="android:paddingHorizontal">@dimen/settingslib_expressive_space_small4</item>
-        <item name="android:textAppearance">@style/TextAppearance.SettingsLib.TitleMedium</item>
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Medium</item>
     </style>
 
     <style name="SettingsLibButtonStyle.Expressive.Outline.Extra"
@@ -105,15 +105,10 @@
     </style>
 
     <style name="SettingslibTextButtonStyle.Expressive"
-        parent="@style/Widget.Material3.Button.TextButton.Icon">
+        parent="@style/Widget.Material3Expressive.Button.TextButton.Icon">
         <item name="android:theme">@style/Theme.Material3.DynamicColors.DayNight</item>
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:textAppearance">@style/TextAppearance.SettingsLib.BodyLarge.Emphasized</item>
-        <item name="android:textColor">@color/settingslib_materialColorOnSurface</item>
-        <item name="iconTint">@null</item>
-        <item name="iconPadding">@dimen/settingslib_expressive_space_extrasmall4</item>
-        <item name="rippleColor">?android:attr/colorControlHighlight</item>
     </style>
 
     <style name="SettingsLibCardStyle" parent="">
diff --git a/packages/SettingsLib/SettingsTheme/res/values/styles_m3_expressive.xml b/packages/SettingsLib/SettingsTheme/res/values/styles_m3_expressive.xml
new file mode 100644
index 0000000..826fe31
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/values/styles_m3_expressive.xml
@@ -0,0 +1,475 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- M3 Expressive filled button style. -->
+    <style name="Widget.Material3Expressive.Button" parent="Widget.Material3.Button">
+        <item name="android:paddingStart">?attr/containerPaddingStart</item>
+        <item name="android:paddingEnd">?attr/containerPaddingEnd</item>
+        <item name="android:paddingTop">?attr/containerPaddingTop</item>
+        <item name="android:paddingBottom">?attr/containerPaddingBottom</item>
+        <item name="android:insetTop">?attr/containerInsetTop</item>
+        <item name="android:insetBottom">?attr/containerInsetBottom</item>
+        <item name="iconPadding">?attr/containerIconPadding</item>
+        <item name="iconSize">?attr/containerIconSize</item>
+        <item name="android:textAppearance">?attr/labelTextAppearance</item>
+        <item name="shapeAppearance">@xml/settingslib_button_shape_state_list</item>
+        <item name="shapeAppearanceOverlay">@null</item>
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Filled</item>
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.Small</item>
+    </style>
+    <style name="Widget.Material3Expressive.Button.Icon"/>
+
+    <!-- M3 Expressive tonal button style. -->
+    <style name="Widget.Material3Expressive.Button.TonalButton">
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Tonal</item>
+    </style>
+    <style name="Widget.Material3Expressive.Button.TonalButton.Icon"/>
+
+    <!-- M3 Expressive outlined button style. -->
+    <style name="Widget.Material3Expressive.Button.OutlinedButton">
+        <item name="android:stateListAnimator" tools:ignore="NewApi">@animator/mtrl_btn_unelevated_state_list_anim</item>
+        <item name="elevation">0dp</item>
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Outlined</item>
+        <item name="strokeColor">@color/settingslib_expressive_button_outline_color_selector</item>
+        <item name="strokeWidth">?attr/containerStrokeWidth</item>
+        <item name="backgroundTint">@color/settingslib_expressive_button_outlined_background_color_selector</item>
+    </style>
+    <style name="Widget.Material3Expressive.Button.OutlinedButton.Icon"/>
+
+    <!-- M3 Expressive text button style. -->
+    <style name="Widget.Material3Expressive.Button.TextButton">
+        <item name="android:stateListAnimator" tools:ignore="NewApi">@animator/mtrl_btn_unelevated_state_list_anim</item>
+        <item name="elevation">0dp</item>
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.TextButton</item>
+    </style>
+    <style name="Widget.Material3Expressive.Button.TextButton.Icon"/>
+
+    <!-- Styles for M3 Expressive Icon Buttons. -->
+
+    <!-- M3 Expressive icon only button without a container or outline style. -->
+    <style name="Widget.Material3Expressive.Button.IconButton">
+        <item name="android:stateListAnimator" tools:ignore="NewApi">@animator/mtrl_btn_unelevated_state_list_anim</item>
+        <item name="elevation">0dp</item>
+        <item name="android:minWidth">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="android:minHeight">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="android:insetLeft">?attr/containerInsetLeft</item>
+        <item name="android:insetRight">?attr/containerInsetRight</item>
+        <item name="iconPadding">@dimen/m3_btn_icon_only_icon_padding</item>
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.IconButton.Standard</item>
+        <item name="materialSizeOverlay">@style/SizeOverlay.Material3Expressive.Button.IconButton.Small</item>
+    </style>
+
+    <!-- M3 Expressive icon only button filled container style. -->
+    <style name="Widget.Material3Expressive.Button.IconButton.Filled">
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Filled</item>
+    </style>
+
+    <!-- M3 Expressive icon only button in tonal container style. -->
+    <style name="Widget.Material3Expressive.Button.IconButton.Tonal">
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Tonal</item>
+    </style>
+
+    <!-- M3 Expressive icon only button with an outline style. -->
+    <style name="Widget.Material3Expressive.Button.IconButton.Outlined">
+        <item name="materialThemeOverlay">@style/ThemeOverlay.Material3Expressive.Button.Outlined</item>
+        <item name="strokeColor">@color/settingslib_expressive_button_outline_color_selector</item>
+        <item name="strokeWidth">?attr/containerStrokeWidth</item>
+        <item name="backgroundTint">@color/settingslib_expressive_button_outlined_background_color_selector</item>
+    </style>
+
+    <!-- Styles for M3 Expressive Button Groups. -->
+
+    <!-- M3 Expressive Button Group. -->
+    <style name="Widget.Material3Expressive.MaterialButtonGroup" parent="Widget.Material3.MaterialButtonGroup"/>
+
+    <!-- M3 Expressive Connected Button Group. -->
+    <style name="Widget.Material3Expressive.MaterialButtonGroup.Connected" parent="Widget.Material3.MaterialButtonGroup.Connected">
+        <item name="innerCornerSize">@xml/settingslib_inner_corner_size_state_list</item>
+    </style>
+
+    <!-- M3 Expressive Button Toggle Group (Segmented Button). -->
+    <style name="Widget.Material3Expressive.MaterialButtonToggleGroup" parent="Widget.Material3.MaterialButtonToggleGroup">
+        <item name="innerCornerSize">@xml/settingslib_inner_corner_size_state_list</item>
+        <item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="android:spacing">@dimen/settingslib_expressive_space_extrasmall1</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlays for different color variants. -->
+
+    <!-- M3 Expressive Button Theme Overlay for the filled color variant. -->
+    <style name="ThemeOverlay.Material3Expressive.Button.Filled" parent="">
+        <item name="colorContainer">?attr/colorPrimary</item>
+        <item name="colorContainerChecked">?attr/colorPrimary</item>
+        <item name="colorContainerUnchecked">?attr/colorSurfaceContainer</item>
+        <item name="colorOnContainer">?attr/colorOnPrimary</item>
+        <item name="colorOnContainerChecked">?attr/colorOnPrimary</item>
+        <item name="colorOnContainerUnchecked">?attr/colorOnSurfaceVariant</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the tonal color variant. -->
+    <style name="ThemeOverlay.Material3Expressive.Button.Tonal" parent="">
+        <item name="colorContainer">?attr/colorSecondaryContainer</item>
+        <item name="colorContainerChecked">?attr/colorSecondary</item>
+        <item name="colorContainerUnchecked">?attr/colorSecondaryContainer</item>
+        <item name="colorOnContainer">?attr/colorOnSecondaryContainer</item>
+        <item name="colorOnContainerChecked">?attr/colorOnSecondary</item>
+        <item name="colorOnContainerUnchecked">?attr/colorOnSecondaryContainer</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the outlined variant. -->
+    <style name="ThemeOverlay.Material3Expressive.Button.Outlined" parent="">
+        <item name="colorContainer">@android:color/transparent</item>
+        <item name="colorContainerChecked">?attr/colorSurfaceInverse</item>
+        <item name="colorContainerUnchecked">@android:color/transparent</item>
+        <item name="colorOnContainer">?attr/colorOnSurfaceVariant</item>
+        <item name="colorOnContainerChecked">?attr/colorOnSurfaceInverse</item>
+        <item name="colorOnContainerUnchecked">?attr/colorOnSurfaceVariant</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the text only variant. -->
+    <style name="ThemeOverlay.Material3Expressive.Button.TextButton" parent="ThemeOverlay.Material3.Button.TextButton">
+        <item name="colorContainerChecked">?attr/colorContainer</item>
+        <item name="colorContainerUnchecked">?attr/colorContainer</item>
+        <item name="colorOnContainerChecked">?attr/colorOnContainer</item>
+        <item name="colorOnContainerUnchecked">?attr/colorOnSurfaceVariant</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the icon only variant. -->
+    <style name="ThemeOverlay.Material3Expressive.Button.IconButton.Standard" parent="">
+        <item name="colorContainer">@android:color/transparent</item>
+        <item name="colorContainerChecked">@android:color/transparent</item>
+        <item name="colorContainerUnchecked">@android:color/transparent</item>
+        <item name="colorOnContainer">?attr/colorOnSurfaceVariant</item>
+        <item name="colorOnContainerChecked">?attr/colorPrimary</item>
+        <item name="colorOnContainerUnchecked">?attr/colorOnSurfaceVariant</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the extra small variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.Xsmall" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall6</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall6</item>
+        <item name="containerPaddingTop">6dp</item>
+        <item name="containerPaddingBottom">6dp</item>
+        <item name="containerInsetTop">8dp</item>
+        <item name="containerInsetBottom">8dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small3</item>
+        <item name="containerIconPadding">@dimen/settingslib_expressive_space_extrasmall4</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="labelTextAppearance">?attr/textAppearanceLabelLarge</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerSmall</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.Xsmall.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the small variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.Small" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerPaddingTop">10dp</item>
+        <item name="containerPaddingBottom">10dp</item>
+        <item name="containerInsetTop">4dp</item>
+        <item name="containerInsetBottom">4dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small3</item>
+        <item name="containerIconPadding">@dimen/settingslib_expressive_space_extrasmall4</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="labelTextAppearance">?attr/textAppearanceLabelLarge</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerSmall</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.Small.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the medium variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.Medium" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerPaddingTop">16dp</item>
+        <item name="containerPaddingBottom">16dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerIconPadding">@dimen/settingslib_expressive_space_extrasmall4</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="labelTextAppearance">?attr/textAppearanceTitleMedium</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.Medium.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerLarge</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the large variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.Large" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="containerPaddingTop">32dp</item>
+        <item name="containerPaddingBottom">32dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_medium1</item>
+        <item name="containerIconPadding">@dimen/settingslib_expressive_space_extrasmall6</item>
+        <item name="containerStrokeWidth">@dimen/settingslib_expressive_space_extrasmall1</item>
+        <item name="labelTextAppearance">?attr/textAppearanceHeadlineSmall</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerExtraLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.Large.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <!-- M3 Expressive Button Theme Overlay for the extra large variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.Xlarge" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_large2</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_large2</item>
+        <item name="containerPaddingTop">48dp</item>
+        <item name="containerPaddingBottom">48dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_medium3</item>
+        <item name="containerIconPadding">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerStrokeWidth">3dp</item>
+        <item name="labelTextAppearance">?attr/textAppearanceHeadlineLarge</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerExtraLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.Xlarge.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <!-- M3 Expressive Icon Button Theme Overlay for the extra small variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall3</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall3</item>
+        <item name="containerPaddingTop">6dp</item>
+        <item name="containerPaddingBottom">6dp</item>
+        <item name="containerInsetTop">8dp</item>
+        <item name="containerInsetBottom">8dp</item>
+        <item name="containerInsetLeft">8dp</item>
+        <item name="containerInsetRight">8dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small3</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerSmall</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall.Narrow">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall2</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall2</item>
+        <item name="containerInsetLeft">10dp</item>
+        <item name="containerInsetRight">10dp</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall.Narrow.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall.Wide">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall5</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall5</item>
+        <item name="containerInsetLeft">4dp</item>
+        <item name="containerInsetRight">4dp</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xsmall.Wide.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <!-- M3 Expressive Icon Button Theme Overlay for the small variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall4</item>
+        <item name="containerPaddingTop">8dp</item>
+        <item name="containerPaddingBottom">8dp</item>
+        <item name="containerInsetTop">4dp</item>
+        <item name="containerInsetBottom">4dp</item>
+        <item name="containerInsetLeft">4dp</item>
+        <item name="containerInsetRight">4dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerSmall</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small.Narrow">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall2</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall2</item>
+        <item name="containerInsetLeft">8dp</item>
+        <item name="containerInsetRight">8dp</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small.Narrow.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small.Wide">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall7</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall7</item>
+        <item name="containerInsetLeft">0dp</item>
+        <item name="containerInsetRight">0dp</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Small.Wide.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerMedium</item>
+    </style>
+
+    <!-- M3 Expressive Icon Button Theme Overlay for the medium variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerPaddingTop">16dp</item>
+        <item name="containerPaddingBottom">16dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerInsetLeft">0dp</item>
+        <item name="containerInsetRight">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerStrokeWidth">1dp</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerMedium</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium.Narrow">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_extrasmall6</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_extrasmall6</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium.Narrow.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium.Wide">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_small4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_small4</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Medium.Wide.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerLarge</item>
+    </style>
+
+    <!-- M3 Expressive Icon Button Theme Overlay for the large variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_medium1</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_medium1</item>
+        <item name="containerPaddingTop">32dp</item>
+        <item name="containerPaddingBottom">32dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerInsetLeft">0dp</item>
+        <item name="containerInsetRight">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_medium1</item>
+        <item name="containerStrokeWidth">@dimen/settingslib_expressive_space_extrasmall1</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerExtraLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large.Narrow">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_small1</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_small1</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large.Narrow.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large.Wide">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_medium4</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Large.Wide.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <!-- M3 Expressive Icon Button Theme Overlay for the extra large variant. -->
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge" parent="">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_medium4</item>
+        <item name="containerPaddingTop">48dp</item>
+        <item name="containerPaddingBottom">48dp</item>
+        <item name="containerInsetTop">0dp</item>
+        <item name="containerInsetBottom">0dp</item>
+        <item name="containerInsetLeft">0dp</item>
+        <item name="containerInsetRight">0dp</item>
+        <item name="containerIconSize">@dimen/settingslib_expressive_space_medium3</item>
+        <item name="containerStrokeWidth">3dp</item>
+        <item name="containerShapePressed">?attr/shapeAppearanceCornerLarge</item>
+        <item name="containerShapeChecked">?attr/shapeAppearanceCornerExtraLarge</item>
+        <item name="containerShapeDefault">@style/ShapeAppearance.Material3.Corner.Full</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge.Narrow">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_medium1</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_medium1</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge.Narrow.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge.Wide">
+        <item name="containerPaddingStart">@dimen/settingslib_expressive_space_large3</item>
+        <item name="containerPaddingEnd">@dimen/settingslib_expressive_space_large3</item>
+    </style>
+    <style name="SizeOverlay.Material3Expressive.Button.IconButton.Xlarge.Wide.Square">
+        <item name="containerShapeChecked">@style/ShapeAppearance.Material3.Corner.Full</item>
+        <item name="containerShapeDefault">?attr/shapeAppearanceCornerExtraLarge</item>
+    </style>
+
+    <!-- M3 shape -->
+    <style name="ShapeAppearance.Material3.Corner.Full" parent="">
+        <item name="cornerFamily">?attr/shapeCornerFamily</item>
+        <item name="cornerSize">50%</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/xml/settingslib_button_shape_state_list.xml b/packages/SettingsLib/SettingsTheme/res/xml/settingslib_button_shape_state_list.xml
new file mode 100644
index 0000000..defedb3
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/xml/settingslib_button_shape_state_list.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_checkable="true" android:state_pressed="true"
+        app:shapeAppearance="?attr/containerShapePressed"/>
+    <item android:state_checked="true"
+        app:shapeAppearance="?attr/containerShapeChecked"/>
+    <item app:shapeAppearance="?attr/containerShapeDefault"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/xml/settingslib_inner_corner_size_state_list.xml b/packages/SettingsLib/SettingsTheme/res/xml/settingslib_inner_corner_size_state_list.xml
new file mode 100644
index 0000000..6e49c7c
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/xml/settingslib_inner_corner_size_state_list.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item android:state_checkable="true" android:state_pressed="true"
+        app:cornerSize="4dp"/>
+    <item android:state_checked="true"
+        app:cornerSize="50%"/>
+    <item app:cornerSize="8dp"/>
+</selector>
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
index 08bedf9..fcaedd2 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
@@ -33,9 +33,8 @@
     val spinnerHorizontalPadding = paddingExtraLarge
     val spinnerVerticalPadding = paddingLarge
 
-    val actionIconWidth = 32.dp
-    val actionIconHeight = 40.dp
-    val actionIconPadding = 4.dp
+    val actionIconSize = 40.dp
+    val actionIconPadding = 8.dp
 
     val itemIconSize = 24.dp
     val itemIconContainerSizeSmall = 40.dp
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt
index 965c971..701825d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsTypography.kt
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.spa.framework.theme
 
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Typography
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
@@ -29,134 +30,428 @@
     private val brand = settingsFontFamily.brand
     private val plain = settingsFontFamily.plain
 
-    val typography = Typography(
-        displayLarge = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 57.sp,
-            lineHeight = 64.sp,
-            letterSpacing = (-0.2).sp,
-            hyphens = Hyphens.Auto,
-        ),
-        displayMedium = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 45.sp,
-            lineHeight = 52.sp,
-            letterSpacing = 0.0.sp,
-            hyphens = Hyphens.Auto,
-        ),
-        displaySmall = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 36.sp,
-            lineHeight = 44.sp,
-            letterSpacing = 0.0.sp,
-            hyphens = Hyphens.Auto,
-        ),
-        headlineLarge = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 32.sp,
-            lineHeight = 40.sp,
-            letterSpacing = 0.0.sp,
-            hyphens = Hyphens.Auto,
-        ),
-        headlineMedium = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 28.sp,
-            lineHeight = 36.sp,
-            letterSpacing = 0.0.sp,
-            hyphens = Hyphens.Auto,
-        ),
-        headlineSmall = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 24.sp,
-            lineHeight = 32.sp,
-            letterSpacing = 0.0.sp,
-            hyphens = Hyphens.Auto,
-        ),
-        titleLarge = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 22.sp,
-            lineHeight = 28.sp,
-            letterSpacing = 0.02.em,
-            hyphens = Hyphens.Auto,
-        ),
-        titleMedium = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 20.sp,
-            lineHeight = 24.sp,
-            letterSpacing = 0.02.em,
-            hyphens = Hyphens.Auto,
-        ),
-        titleSmall = TextStyle(
-            fontFamily = brand,
-            fontWeight = FontWeight.Normal,
-            fontSize = 18.sp,
-            lineHeight = 20.sp,
-            letterSpacing = 0.02.em,
-            hyphens = Hyphens.Auto,
-        ),
-        bodyLarge = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Normal,
-            fontSize = 16.sp,
-            lineHeight = 24.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-        bodyMedium = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Normal,
-            fontSize = 14.sp,
-            lineHeight = 20.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-        bodySmall = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Normal,
-            fontSize = 12.sp,
-            lineHeight = 16.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-        labelLarge = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Medium,
-            fontSize = 16.sp,
-            lineHeight = 24.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-        labelMedium = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Medium,
-            fontSize = 14.sp,
-            lineHeight = 20.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-        labelSmall = TextStyle(
-            fontFamily = plain,
-            fontWeight = FontWeight.Medium,
-            fontSize = 12.sp,
-            lineHeight = 16.sp,
-            letterSpacing = 0.01.em,
-            hyphens = Hyphens.Auto,
-        ),
-    )
+    val typography =
+        Typography(
+            displayLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 57.sp,
+                    lineHeight = 64.sp,
+                    letterSpacing = (-0.2).sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displayMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 45.sp,
+                    lineHeight = 52.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displaySmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 36.sp,
+                    lineHeight = 44.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 32.sp,
+                    lineHeight = 40.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 28.sp,
+                    lineHeight = 36.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineSmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 24.sp,
+                    lineHeight = 32.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 22.sp,
+                    lineHeight = 28.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 20.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleSmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 18.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyLarge =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyMedium =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodySmall =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelLarge =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelMedium =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelSmall =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+        )
+
+    @OptIn(ExperimentalMaterial3ExpressiveApi::class)
+    val expressiveTypography =
+        Typography(
+            displayLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 57.sp,
+                    lineHeight = 64.sp,
+                    letterSpacing = (-0.2).sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displayLargeEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 57.sp,
+                    lineHeight = 64.sp,
+                    letterSpacing = (-0.2).sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displayMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 45.sp,
+                    lineHeight = 52.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displayMediumEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 45.sp,
+                    lineHeight = 52.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displaySmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 36.sp,
+                    lineHeight = 44.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            displaySmallEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 36.sp,
+                    lineHeight = 44.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 32.sp,
+                    lineHeight = 40.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineLargeEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 32.sp,
+                    lineHeight = 40.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 28.sp,
+                    lineHeight = 36.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineMediumEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 28.sp,
+                    lineHeight = 36.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineSmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 24.sp,
+                    lineHeight = 32.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            headlineSmallEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 24.sp,
+                    lineHeight = 32.sp,
+                    letterSpacing = 0.0.sp,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleLarge =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 22.sp,
+                    lineHeight = 28.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleLargeEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 22.sp,
+                    lineHeight = 28.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleMedium =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleMediumEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleSmall =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            titleSmallEmphasized =
+                TextStyle(
+                    fontFamily = brand,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.02.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyLarge =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyLargeEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 16.sp,
+                    lineHeight = 24.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyMedium =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodyMediumEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodySmall =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Normal,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            bodySmallEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelLarge =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelLargeEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 14.sp,
+                    lineHeight = 20.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelMedium =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelMediumEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 12.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelSmall =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.Medium,
+                    fontSize = 11.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+            labelSmallEmphasized =
+                TextStyle(
+                    fontFamily = plain,
+                    fontWeight = FontWeight.SemiBold,
+                    fontSize = 11.sp,
+                    lineHeight = 16.sp,
+                    letterSpacing = 0.01.em,
+                    hyphens = Hyphens.Auto,
+                ),
+        )
 }
 
 @Composable
 internal fun rememberSettingsTypography(): Typography {
     val settingsFontFamily = rememberSettingsFontFamily()
-    return remember { SettingsTypography(settingsFontFamily).typography }
+    return remember {
+        if (isSpaExpressiveEnabled) SettingsTypography(settingsFontFamily).expressiveTypography
+        else SettingsTypography(settingsFontFamily).typography
+    }
 }
 
 /** Creates a new [TextStyle] which font weight set to medium. */
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
index 203a8bd..adebccb 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
@@ -56,7 +56,6 @@
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.theme.divider
 import com.android.settingslib.spa.framework.theme.isSpaExpressiveEnabled
-import com.android.settingslib.spa.framework.theme.toSemiBoldWeight
 
 data class ActionButton(
     val text: String,
@@ -130,7 +129,7 @@
                 Text(
                     text = actionButton.text,
                     textAlign = TextAlign.Center,
-                    style = MaterialTheme.typography.labelLarge.toSemiBoldWeight(),
+                    style = MaterialTheme.typography.titleSmall,
                 )
             }
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/IntroPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/IntroPreference.kt
index 6d3f7bc..c786dde 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/IntroPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/IntroPreference.kt
@@ -36,7 +36,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.theme.SettingsDimension
-import com.android.settingslib.spa.framework.theme.toSemiBoldWeight
 
 @Composable
 fun IntroPreference(
@@ -113,7 +112,7 @@
         Text(
             text = title,
             textAlign = TextAlign.Center,
-            style = MaterialTheme.typography.titleLarge.toSemiBoldWeight(),
+            style = MaterialTheme.typography.titleLarge,
             color = MaterialTheme.colorScheme.onSurface,
         )
     }
@@ -127,7 +126,7 @@
             Text(
                 text = description,
                 textAlign = TextAlign.Center,
-                style = MaterialTheme.typography.bodyLarge,
+                style = MaterialTheme.typography.titleMedium,
                 color = MaterialTheme.colorScheme.onSurfaceVariant,
                 modifier = Modifier.padding(top = SettingsDimension.paddingExtraSmall),
             )
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt
index 5419223..3ebe18d 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ZeroStatePreference.kt
@@ -23,6 +23,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.History
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
@@ -47,8 +48,8 @@
 import androidx.graphics.shapes.RoundedPolygon
 import androidx.graphics.shapes.star
 import androidx.graphics.shapes.toPath
-import com.android.settingslib.spa.framework.theme.toSemiBoldWeight
 
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun ZeroStatePreference(icon: ImageVector, text: String? = null, description: String? = null) {
     val zeroStateShape = remember {
@@ -81,7 +82,7 @@
             Text(
                 text = text,
                 textAlign = TextAlign.Center,
-                style = MaterialTheme.typography.titleMedium.toSemiBoldWeight(),
+                style = MaterialTheme.typography.titleMediumEmphasized,
                 color = MaterialTheme.colorScheme.onSurfaceVariant,
                 modifier = Modifier.padding(top = 24.dp),
             )
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
index f99d206..668f683 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/Actions.kt
@@ -56,32 +56,27 @@
     IconButton(
         onClick = onClick,
         modifier =
-        if (isSpaExpressiveEnabled)
-            Modifier
-                .padding(
-                    start = SettingsDimension.paddingLarge,
-                    end = SettingsDimension.paddingSmall,
-                    top = SettingsDimension.paddingExtraSmall,
-                    bottom = SettingsDimension.paddingExtraSmall,
-                )
-                .size(SettingsDimension.actionIconWidth, SettingsDimension.actionIconHeight)
-                .clip(SettingsShape.CornerExtraLarge)
-        else Modifier,
+            if (isSpaExpressiveEnabled)
+                Modifier.padding(
+                        start = SettingsDimension.paddingExtraSmall5,
+                        end = SettingsDimension.paddingSmall,
+                        top = SettingsDimension.paddingExtraSmall,
+                        bottom = SettingsDimension.paddingExtraSmall,
+                    )
+                    .size(SettingsDimension.actionIconSize)
+                    .clip(SettingsShape.CornerExtraLarge)
+            else Modifier,
     ) {
         Icon(
             imageVector = Icons.AutoMirrored.Outlined.ArrowBack,
             contentDescription = contentDescription,
             modifier =
-            if (isSpaExpressiveEnabled)
-                Modifier
-                    .size(
-                        SettingsDimension.actionIconWidth,
-                        SettingsDimension.actionIconHeight,
-                    )
-                    .clip(SettingsShape.CornerExtraLarge)
-                    .background(MaterialTheme.colorScheme.surfaceContainerHighest)
-                    .padding(SettingsDimension.actionIconPadding)
-            else Modifier,
+                if (isSpaExpressiveEnabled)
+                    Modifier.size(SettingsDimension.actionIconSize)
+                        .clip(SettingsShape.CornerExtraLarge)
+                        .background(MaterialTheme.colorScheme.surfaceContainerHighest)
+                        .padding(SettingsDimension.actionIconPadding)
+                else Modifier,
         )
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
index 693fb35..0c0ece4 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/CustomizedAppBar.kt
@@ -142,10 +142,11 @@
     Text(
         text = title,
         modifier =
-            Modifier.padding(
+            Modifier
+                .padding(
                     start =
-                        if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall
-                        else SettingsDimension.itemPaddingAround,
+                    if (isSpaExpressiveEnabled) SettingsDimension.paddingExtraSmall
+                    else SettingsDimension.itemPaddingAround,
                     end = SettingsDimension.itemPaddingEnd,
                 )
                 .semantics { heading() },
@@ -156,13 +157,22 @@
 
 @Composable
 private fun topAppBarColors() =
-    TopAppBarColors(
-        containerColor = MaterialTheme.colorScheme.settingsBackground,
-        scrolledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
-        navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
-        titleContentColor = MaterialTheme.colorScheme.onSurface,
-        actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
-    )
+    if (isSpaExpressiveEnabled)
+        TopAppBarColors(
+            containerColor = MaterialTheme.colorScheme.surfaceContainer,
+            scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
+            navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
+            titleContentColor = MaterialTheme.colorScheme.onSurface,
+            actionIconContentColor = MaterialTheme.colorScheme.primary,
+        )
+    else
+        TopAppBarColors(
+            containerColor = MaterialTheme.colorScheme.settingsBackground,
+            scrolledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
+            navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
+            titleContentColor = MaterialTheme.colorScheme.onSurface,
+            actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
+        )
 
 /**
  * Represents the colors used by a top app bar in different states.
@@ -257,14 +267,16 @@
     // Compose a Surface with a TopAppBarLayout content.
     Box(
         modifier =
-            Modifier.drawBehind { drawRect(color = colors.scrolledContainerColor) }
+            Modifier
+                .drawBehind { drawRect(color = colors.scrolledContainerColor) }
                 .semantics { isTraversalGroup = true }
                 .pointerInput(Unit) {}
     ) {
         val height = LocalDensity.current.run { ContainerHeight.toPx() }
         TopAppBarLayout(
             modifier =
-                Modifier.windowInsetsPadding(windowInsets)
+                Modifier
+                    .windowInsetsPadding(windowInsets)
                     // clip after padding so we don't show the title over the inset area
                     .clipToBounds(),
             heightPx = height,
@@ -387,7 +399,8 @@
         Column {
             TopAppBarLayout(
                 modifier =
-                    Modifier.windowInsetsPadding(windowInsets)
+                    Modifier
+                        .windowInsetsPadding(windowInsets)
                         // clip after padding so we don't show the title over the inset area
                         .clipToBounds(),
                 heightPx = pinnedHeightPx,
@@ -495,14 +508,17 @@
 ) {
     Layout(
         {
-            Box(Modifier.layoutId("navigationIcon").padding(start = TopAppBarHorizontalPadding)) {
+            Box(Modifier
+                .layoutId("navigationIcon")
+                .padding(start = TopAppBarHorizontalPadding)) {
                 CompositionLocalProvider(
                     LocalContentColor provides navigationIconContentColor,
                     content = navigationIcon,
                 )
             }
             Box(
-                Modifier.layoutId("title")
+                Modifier
+                    .layoutId("title")
                     .padding(horizontal = TopAppBarHorizontalPadding)
                     .then(if (hideTitleSemantics) Modifier.clearAndSetSemantics {} else Modifier)
                     .graphicsLayer { alpha = titleAlpha() }
@@ -521,7 +537,9 @@
                     )
                 }
             }
-            Box(Modifier.layoutId("actionIcons").padding(end = TopAppBarHorizontalPadding)) {
+            Box(Modifier
+                .layoutId("actionIcons")
+                .padding(end = TopAppBarHorizontalPadding)) {
                 CompositionLocalProvider(
                     LocalContentColor provides actionIconContentColor,
                     content = actions,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
index 62bc00a..f10f96a 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Category.kt
@@ -28,6 +28,7 @@
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.TouchApp
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
@@ -51,6 +52,7 @@
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 
 /** A category title that is placed before a group of similar items. */
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
 @Composable
 fun CategoryTitle(title: String) {
     Text(
@@ -67,7 +69,9 @@
                 bottom = 8.dp,
             ),
         color = MaterialTheme.colorScheme.primary,
-        style = MaterialTheme.typography.labelMedium,
+        style =
+            if (isSpaExpressiveEnabled) MaterialTheme.typography.labelLargeEmphasized
+            else MaterialTheme.typography.labelMedium,
     )
 }
 
@@ -76,7 +80,11 @@
  * visually separates groups of items.
  */
 @Composable
-fun Category(title: String? = null, modifier: Modifier = Modifier, content: @Composable ColumnScope.() -> Unit) {
+fun Category(
+    title: String? = null,
+    modifier: Modifier = Modifier,
+    content: @Composable ColumnScope.() -> Unit,
+) {
     var displayTitle by remember { mutableStateOf(false) }
     Column(
         modifier =
@@ -90,7 +98,8 @@
         if (title != null && displayTitle) CategoryTitle(title = title)
         Column(
             modifier =
-                modifier.onGloballyPositioned { coordinates ->
+                modifier
+                    .onGloballyPositioned { coordinates ->
                         displayTitle = coordinates.size.height > 0
                     }
                     .then(
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
index 6e4fd78..03777cc 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/ui/Spinner.kt
@@ -195,7 +195,9 @@
                     else Modifier
                 ),
         color = color,
-        style = MaterialTheme.typography.labelLarge,
+        style =
+            if (isSpaExpressiveEnabled) MaterialTheme.typography.titleMedium
+            else MaterialTheme.typography.labelLarge,
     )
 }
 
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 1a043d5..cc996c5 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -97,6 +97,7 @@
     name: "settings_catalyst"
     namespace: "android_settings"
     description: "Settings catalyst project migration"
+    is_exported: true
     bug: "323791114"
     is_exported: true
 }
@@ -106,6 +107,7 @@
     is_fixed_read_only: true
     namespace: "android_settings"
     description: "Enable WRITE_SYSTEM_PREFERENCE permission and appop"
+    is_exported: true
     bug: "375193223"
     is_exported: true
 }
@@ -197,3 +199,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "disable_audio_sharing_auto_pick_fallback_in_ui"
+    namespace: "cross_device_experiences"
+    description: "Do not auto pick audio sharing fallback device in UI"
+    bug: "383469911"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e1929b7..6cf9e83 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -229,6 +229,8 @@
     <string name="bluetooth_hearing_aid_right_active">Active (right only)</string>
     <!-- Connected device settings. Message when the left-side and right-side hearing aids device are active. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_hearing_aid_left_and_right_active">Active (left and right)</string>
+    <!-- Connected device settings.: Message when changing remote ambient state failed. [CHAR LIMIT=NONE] -->
+    <string name="bluetooth_hearing_device_ambient_error">Couldn\u2019t update surroundings</string>
 
     <!-- Connected devices settings. Message when Bluetooth is connected and active for media only, showing remote device status and battery level. [CHAR LIMIT=NONE] -->
     <string name="bluetooth_active_media_only_battery_level">Active (media only). <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery.</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUi.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUi.java
new file mode 100644
index 0000000..881a97b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUi.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
+
+import android.bluetooth.BluetoothDevice;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.List;
+import java.util.Map;
+
+/** Interface for the ambient volume UI. */
+public interface AmbientVolumeUi {
+
+    /** Interface definition for a callback to be invoked when event happens in AmbientVolumeUi. */
+    interface AmbientVolumeUiListener {
+        /** Called when the expand icon is clicked. */
+        void onExpandIconClick();
+
+        /** Called when the ambient volume icon is clicked. */
+        void onAmbientVolumeIconClick();
+
+        /** Called when the slider of the specified side is changed. */
+        void onSliderValueChange(int side, int value);
+    };
+
+    /** The rotation degree of the expand icon when the UI is in collapsed mode. */
+    float ROTATION_COLLAPSED = 0f;
+    /** The rotation degree of the expand icon when the UI is in expanded mode. */
+    float ROTATION_EXPANDED = 180f;
+
+    /**
+     * The default ambient volume level for hearing device ambient volume icon
+     *
+     * <p> This icon visually represents the current ambient volume. It displays separate
+     * levels for the left and right sides, each with 5 levels ranging from 0 to 4.
+     *
+     * <p> To represent the combined left/right levels with a single value, the following
+     * calculation is used:
+     *      finalLevel = (leftLevel * 5) + rightLevel
+     * For example:
+     * <ul>
+     *    <li>If left level is 2 and right level is 3, the final level will be 13 (2 * 5 + 3)</li>
+     *    <li>If both left and right levels are 0, the final level will be 0</li>
+     *    <li>If both left and right levels are 4, the final level will be 24</li>
+     * </ul>
+     */
+    int AMBIENT_VOLUME_LEVEL_DEFAULT = 24;
+    /**
+     * The minimum ambient volume level for hearing device ambient volume icon
+     *
+     * @see #AMBIENT_VOLUME_LEVEL_DEFAULT
+     */
+    int AMBIENT_VOLUME_LEVEL_MIN = 0;
+    /**
+     * The maximum ambient volume level for hearing device ambient volume icon
+     *
+     * @see #AMBIENT_VOLUME_LEVEL_DEFAULT
+     */
+    int AMBIENT_VOLUME_LEVEL_MAX = 24;
+
+    /**
+     * Ths side identifier for slider in collapsed mode which can unified control the ambient
+     * volume of all devices in the same set.
+     */
+    int SIDE_UNIFIED = 999;
+
+    /** All valid side of the sliders in the UI. */
+    List<Integer> VALID_SIDES = List.of(SIDE_UNIFIED, SIDE_LEFT, SIDE_RIGHT);
+
+    /** Sets if the UI is visible. */
+    void setVisible(boolean visible);
+
+    /**
+     * Sets if the UI is expandable between expanded and collapsed mode.
+     *
+     * <p> If the UI is not expandable, it implies the UI will always stay in collapsed mode
+     */
+    void setExpandable(boolean expandable);
+
+    /** @return if the UI is expandable. */
+    boolean isExpandable();
+
+    /** Sets if the UI is in expanded mode. */
+    void setExpanded(boolean expanded);
+
+    /** @return if the UI is in expanded mode. */
+    boolean isExpanded();
+
+    /**
+     * Sets if the UI is capable to mute the ambient of the remote device.
+     *
+     * <p> If the value is {@code false}, it implies the remote device ambient will always be
+     * unmute and can not be mute from the UI
+     */
+    void setMutable(boolean mutable);
+
+    /** @return if the UI is capable to mute the ambient of remote device. */
+    boolean isMutable();
+
+    /** Sets if the UI shows mute state. */
+    void setMuted(boolean muted);
+
+    /** @return if the UI shows mute state */
+    boolean isMuted();
+
+    /**
+     * Sets listener on the UI.
+     *
+     * @see AmbientVolumeUiListener
+     */
+    void setListener(@Nullable AmbientVolumeUiListener listener);
+
+    /**
+     * Sets up sliders in the UI.
+     *
+     * <p> For each side of device, the UI should hava a corresponding slider to control it's
+     * ambient volume.
+     * <p> For all devices in the same set, the UI should have a slider to control all devices'
+     * ambient volume at once.
+     * @param sideToDeviceMap the side and device mapping of all devices in the same set
+     */
+    void setupSliders(@NonNull Map<Integer, BluetoothDevice> sideToDeviceMap);
+
+    /**
+     * Sets if the slider is enabled.
+     *
+     * @param side the side of the slider
+     * @param enabled the enabled state
+     */
+    void setSliderEnabled(int side, boolean enabled);
+
+    /**
+     * Sets the slider value.
+     *
+     * @param side the side of the slider
+     * @param value the ambient value
+     */
+    void setSliderValue(int side, int value);
+
+    /**
+     * Sets the slider's minimum and maximum value.
+     *
+     * @param side the side of the slider
+     * @param min the minimum ambient value
+     * @param max the maximum ambient value
+     */
+    void setSliderRange(int side, int min, int max);
+
+    /** Updates the UI according to current state. */
+    void updateLayout();
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUiController.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUiController.java
new file mode 100644
index 0000000..ce392b12
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/AmbientVolumeUiController.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static android.bluetooth.AudioInputControl.MUTE_NOT_MUTED;
+import static android.bluetooth.AudioInputControl.MUTE_MUTED;
+import static android.bluetooth.BluetoothDevice.BOND_BONDED;
+
+import static com.android.settingslib.bluetooth.AmbientVolumeUi.SIDE_UNIFIED;
+import static com.android.settingslib.bluetooth.AmbientVolumeUi.VALID_SIDES;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_INVALID;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
+import static com.android.settingslib.bluetooth.HearingDeviceLocalDataManager.Data.INVALID_VOLUME;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.util.ArraySet;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settingslib.R;
+import com.android.settingslib.utils.ThreadUtils;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+
+import java.util.Map;
+import java.util.Set;
+
+/** This class controls ambient volume UI with local and remote ambient data. */
+public class AmbientVolumeUiController implements
+        HearingDeviceLocalDataManager.OnDeviceLocalDataChangeListener,
+        AmbientVolumeController.AmbientVolumeControlCallback,
+        AmbientVolumeUi.AmbientVolumeUiListener, BluetoothCallback, CachedBluetoothDevice.Callback {
+
+    private static final boolean DEBUG = true;
+    private static final String TAG = "AmbientVolumeUiController";
+
+    private final Context mContext;
+    private final LocalBluetoothProfileManager mProfileManager;
+    private final BluetoothEventManager mEventManager;
+    private final AmbientVolumeUi mAmbientLayout;
+    private final AmbientVolumeController mVolumeController;
+    private final HearingDeviceLocalDataManager mLocalDataManager;
+
+    private final Set<CachedBluetoothDevice> mCachedDevices = new ArraySet<>();
+    private final BiMap<Integer, BluetoothDevice> mSideToDeviceMap = HashBiMap.create();
+    private CachedBluetoothDevice mCachedDevice;
+    private boolean mShowUiWhenLocalDataExist = true;
+
+    public AmbientVolumeUiController(@NonNull Context context,
+            @NonNull LocalBluetoothManager bluetoothManager,
+            @NonNull AmbientVolumeUi ambientLayout) {
+        mContext = context;
+        mProfileManager = bluetoothManager.getProfileManager();
+        mEventManager = bluetoothManager.getEventManager();
+        mAmbientLayout = ambientLayout;
+        mAmbientLayout.setListener(this);
+        mVolumeController = new AmbientVolumeController(mProfileManager, this);
+        mLocalDataManager = new HearingDeviceLocalDataManager(context);
+        mLocalDataManager.setOnDeviceLocalDataChangeListener(this,
+                ThreadUtils.getBackgroundExecutor());
+    }
+
+    @VisibleForTesting
+    public AmbientVolumeUiController(@NonNull Context context,
+            @NonNull LocalBluetoothManager bluetoothManager,
+            @NonNull AmbientVolumeUi ambientLayout,
+            @NonNull AmbientVolumeController volumeController,
+            @NonNull HearingDeviceLocalDataManager localDataManager) {
+        mContext = context;
+        mProfileManager = bluetoothManager.getProfileManager();
+        mEventManager = bluetoothManager.getEventManager();
+        mAmbientLayout = ambientLayout;
+        mVolumeController = volumeController;
+        mLocalDataManager = localDataManager;
+    }
+
+
+    @Override
+    public void onDeviceLocalDataChange(@NonNull String address,
+            @Nullable HearingDeviceLocalDataManager.Data data) {
+        if (data == null) {
+            // The local data is removed because the device is unpaired, do nothing
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "onDeviceLocalDataChange, address:" + address + ", data:" + data);
+        }
+        for (BluetoothDevice device : mSideToDeviceMap.values()) {
+            if (device.getAnonymizedAddress().equals(address)) {
+                postOnMainThread(() -> loadLocalDataToUi(device));
+                return;
+            }
+        }
+    }
+
+    @Override
+    public void onVolumeControlServiceConnected() {
+        mCachedDevices.forEach(device -> mVolumeController.registerCallback(
+                ThreadUtils.getBackgroundExecutor(), device.getDevice()));
+    }
+
+    @Override
+    public void onAmbientChanged(@NonNull BluetoothDevice device, int gainSettings) {
+        if (DEBUG) {
+            Log.d(TAG, "onAmbientChanged, value:" + gainSettings + ", device:" + device);
+        }
+        HearingDeviceLocalDataManager.Data data = mLocalDataManager.get(device);
+        final boolean expanded = mAmbientLayout.isExpanded();
+        final boolean isInitiatedFromUi = (expanded && data.ambient() == gainSettings)
+                || (!expanded && data.groupAmbient() == gainSettings);
+        if (isInitiatedFromUi) {
+            // The change is initiated from UI, no need to update UI
+            return;
+        }
+
+        // We have to check if we need to expand the controls by getting all remote
+        // device's ambient value, delay for a while to wait all remote devices update
+        // to the latest value to avoid unnecessary expand action.
+        postDelayedOnMainThread(this::refresh, 1200L);
+    }
+
+    @Override
+    public void onMuteChanged(@NonNull BluetoothDevice device, int mute) {
+        if (DEBUG) {
+            Log.d(TAG, "onMuteChanged, mute:" + mute + ", device:" + device);
+        }
+        final boolean muted = mAmbientLayout.isMuted();
+        boolean isInitiatedFromUi = (muted && mute == MUTE_MUTED)
+                || (!muted && mute == MUTE_NOT_MUTED);
+        if (isInitiatedFromUi) {
+            // The change is initiated from UI, no need to update UI
+            return;
+        }
+
+        // We have to check if we need to mute the devices by getting all remote
+        // device's mute state, delay for a while to wait all remote devices update
+        // to the latest value.
+        postDelayedOnMainThread(this::refresh, 1200L);
+    }
+
+    @Override
+    public void onCommandFailed(@NonNull BluetoothDevice device) {
+        Log.w(TAG, "onCommandFailed, device:" + device);
+        postOnMainThread(() -> {
+            showErrorToast(R.string.bluetooth_hearing_device_ambient_error);
+            refresh();
+        });
+    }
+
+    @Override
+    public void onExpandIconClick() {
+        mSideToDeviceMap.forEach((s, d) -> {
+            if (!mAmbientLayout.isMuted()) {
+                // Apply previous collapsed/expanded volume to remote device
+                HearingDeviceLocalDataManager.Data data = mLocalDataManager.get(d);
+                int volume = mAmbientLayout.isExpanded()
+                        ? data.ambient() : data.groupAmbient();
+                mVolumeController.setAmbient(d, volume);
+            }
+            // Update new value to local data
+            mLocalDataManager.updateAmbientControlExpanded(d,
+                    mAmbientLayout.isExpanded());
+        });
+        mLocalDataManager.flush();
+    }
+
+    @Override
+    public void onAmbientVolumeIconClick() {
+        if (!mAmbientLayout.isMuted()) {
+            loadLocalDataToUi();
+        }
+        for (BluetoothDevice device : mSideToDeviceMap.values()) {
+            mVolumeController.setMuted(device, mAmbientLayout.isMuted());
+        }
+    }
+
+    @Override
+    public void onSliderValueChange(int side, int value) {
+        if (DEBUG) {
+            Log.d(TAG, "onSliderValueChange: side=" + side + ", value=" + value);
+        }
+        setVolumeIfValid(side, value);
+
+        Runnable setAmbientRunnable = () -> {
+            if (side == SIDE_UNIFIED) {
+                mSideToDeviceMap.forEach((s, d) -> mVolumeController.setAmbient(d, value));
+            } else {
+                final BluetoothDevice device = mSideToDeviceMap.get(side);
+                mVolumeController.setAmbient(device, value);
+            }
+        };
+
+        if (mAmbientLayout.isMuted()) {
+            // User drag on the volume slider when muted. Unmute the devices first.
+            mAmbientLayout.setMuted(false);
+
+            for (BluetoothDevice device : mSideToDeviceMap.values()) {
+                mVolumeController.setMuted(device, false);
+            }
+            // Restore the value before muted
+            loadLocalDataToUi();
+            // Delay set ambient on remote device since the immediately sequential command
+            // might get failed sometimes
+            postDelayedOnMainThread(setAmbientRunnable, 1000L);
+        } else {
+            setAmbientRunnable.run();
+        }
+    }
+
+    @Override
+    public void onProfileConnectionStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
+            int state, int bluetoothProfile) {
+        if (bluetoothProfile == BluetoothProfile.VOLUME_CONTROL
+                && state == BluetoothProfile.STATE_CONNECTED
+                && mCachedDevices.contains(cachedDevice)) {
+            // After VCP connected, AICS may not ready yet and still return invalid value, delay
+            // a while to wait AICS ready as a workaround
+            postDelayedOnMainThread(this::refresh, 1000L);
+        }
+    }
+
+    @Override
+    public void onDeviceAttributesChanged() {
+        mCachedDevices.forEach(device -> {
+            device.unregisterCallback(this);
+            mVolumeController.unregisterCallback(device.getDevice());
+        });
+        postOnMainThread(()-> {
+            loadDevice(mCachedDevice);
+            ThreadUtils.postOnBackgroundThread(()-> {
+                mCachedDevices.forEach(device -> {
+                    device.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
+                    mVolumeController.registerCallback(ThreadUtils.getBackgroundExecutor(),
+                            device.getDevice());
+                });
+            });
+        });
+    }
+
+    /**
+     * Registers callbacks and listeners, this should be called when needs to start listening to
+     * events.
+     */
+    public void start() {
+        mEventManager.registerCallback(this);
+        mLocalDataManager.start();
+        mCachedDevices.forEach(device -> {
+            device.registerCallback(ThreadUtils.getBackgroundExecutor(), this);
+            mVolumeController.registerCallback(ThreadUtils.getBackgroundExecutor(),
+                    device.getDevice());
+        });
+    }
+
+    /**
+     * Unregisters callbacks and listeners, this should be called when no longer needs to listen to
+     * events.
+     */
+    public void stop() {
+        mEventManager.unregisterCallback(this);
+        mLocalDataManager.stop();
+        mCachedDevices.forEach(device -> {
+            device.unregisterCallback(this);
+            mVolumeController.unregisterCallback(device.getDevice());
+        });
+    }
+
+    /**
+     * Loads all devices in the same set with {@code cachedDevice} and create corresponding sliders.
+     *
+     * <p>If the devices has valid ambient control points, the ambient volume UI will be visible.
+     * @param cachedDevice the remote device
+     */
+    public void loadDevice(CachedBluetoothDevice cachedDevice) {
+        if (DEBUG) {
+            Log.d(TAG, "loadDevice, device=" + cachedDevice);
+        }
+        mCachedDevice = cachedDevice;
+        mSideToDeviceMap.clear();
+        mCachedDevices.clear();
+        boolean deviceSupportVcp =
+                cachedDevice != null && cachedDevice.getProfiles().stream().anyMatch(
+                        p -> p instanceof VolumeControlProfile);
+        if (!deviceSupportVcp) {
+            mAmbientLayout.setVisible(false);
+            return;
+        }
+
+        // load devices in the same set
+        if (VALID_SIDES.contains(cachedDevice.getDeviceSide())
+                && cachedDevice.getBondState() == BOND_BONDED) {
+            mSideToDeviceMap.put(cachedDevice.getDeviceSide(), cachedDevice.getDevice());
+            mCachedDevices.add(cachedDevice);
+        }
+        for (CachedBluetoothDevice memberDevice : cachedDevice.getMemberDevice()) {
+            if (VALID_SIDES.contains(memberDevice.getDeviceSide())
+                    && memberDevice.getBondState() == BOND_BONDED) {
+                mSideToDeviceMap.put(memberDevice.getDeviceSide(), memberDevice.getDevice());
+                mCachedDevices.add(memberDevice);
+            }
+        }
+
+        mAmbientLayout.setExpandable(mSideToDeviceMap.size() >  1);
+        mAmbientLayout.setupSliders(mSideToDeviceMap);
+        refresh();
+    }
+
+    /** Refreshes the ambient volume UI. */
+    public void refresh() {
+        if (isAmbientControlAvailable()) {
+            mAmbientLayout.setVisible(true);
+            loadRemoteDataToUi();
+        } else {
+            mAmbientLayout.setVisible(false);
+        }
+    }
+
+    /** Sets if the ambient volume UI should be visible when local ambient data exist. */
+    public void setShowUiWhenLocalDataExist(boolean shouldShow) {
+        mShowUiWhenLocalDataExist = shouldShow;
+    }
+
+    /** Updates the ambient sliders according to current state. */
+    private void updateSliderUi() {
+        boolean isAnySliderEnabled = false;
+        for (Map.Entry<Integer, BluetoothDevice> entry : mSideToDeviceMap.entrySet()) {
+            final int side = entry.getKey();
+            final BluetoothDevice device = entry.getValue();
+            final boolean enabled = isDeviceConnectedToVcp(device)
+                    && mVolumeController.isAmbientControlAvailable(device);
+            isAnySliderEnabled |= enabled;
+            mAmbientLayout.setSliderEnabled(side, enabled);
+        }
+        mAmbientLayout.setSliderEnabled(SIDE_UNIFIED, isAnySliderEnabled);
+        mAmbientLayout.updateLayout();
+    }
+
+    /** Sets the ambient to the corresponding control slider. */
+    private void setVolumeIfValid(int side, int volume) {
+        if (volume == INVALID_VOLUME) {
+            return;
+        }
+        mAmbientLayout.setSliderValue(side, volume);
+        // Update new value to local data
+        if (side == SIDE_UNIFIED) {
+            mSideToDeviceMap.forEach((s, d) -> mLocalDataManager.updateGroupAmbient(d, volume));
+        } else {
+            mLocalDataManager.updateAmbient(mSideToDeviceMap.get(side), volume);
+        }
+        mLocalDataManager.flush();
+    }
+
+    private void loadLocalDataToUi() {
+        mSideToDeviceMap.forEach((s, d) -> loadLocalDataToUi(d));
+    }
+
+    private void loadLocalDataToUi(BluetoothDevice device) {
+        final HearingDeviceLocalDataManager.Data data = mLocalDataManager.get(device);
+        if (DEBUG) {
+            Log.d(TAG, "loadLocalDataToUi, data=" + data + ", device=" + device);
+        }
+        if (isDeviceConnectedToVcp(device) && !mAmbientLayout.isMuted()) {
+            final int side = mSideToDeviceMap.inverse().getOrDefault(device, SIDE_INVALID);
+            setVolumeIfValid(side, data.ambient());
+            setVolumeIfValid(SIDE_UNIFIED, data.groupAmbient());
+        }
+        setAmbientControlExpanded(data.ambientControlExpanded());
+        updateSliderUi();
+    }
+
+    private void loadRemoteDataToUi() {
+        BluetoothDevice leftDevice = mSideToDeviceMap.get(SIDE_LEFT);
+        AmbientVolumeController.RemoteAmbientState leftState =
+                mVolumeController.refreshAmbientState(leftDevice);
+        BluetoothDevice rightDevice = mSideToDeviceMap.get(SIDE_RIGHT);
+        AmbientVolumeController.RemoteAmbientState rightState =
+                mVolumeController.refreshAmbientState(rightDevice);
+        if (DEBUG) {
+            Log.d(TAG, "loadRemoteDataToUi, left=" + leftState + ", right=" + rightState);
+        }
+        mSideToDeviceMap.forEach((side, device) -> {
+            int ambientMax = mVolumeController.getAmbientMax(device);
+            int ambientMin = mVolumeController.getAmbientMin(device);
+            if (ambientMin != ambientMax) {
+                mAmbientLayout.setSliderRange(side, ambientMin, ambientMax);
+                mAmbientLayout.setSliderRange(SIDE_UNIFIED, ambientMin, ambientMax);
+            }
+        });
+
+        // Update ambient volume
+        final int leftAmbient = leftState != null ? leftState.gainSetting() : INVALID_VOLUME;
+        final int rightAmbient = rightState != null ? rightState.gainSetting() : INVALID_VOLUME;
+        if (mAmbientLayout.isExpanded()) {
+            setVolumeIfValid(SIDE_LEFT, leftAmbient);
+            setVolumeIfValid(SIDE_RIGHT, rightAmbient);
+        } else {
+            if (leftAmbient != rightAmbient && leftAmbient != INVALID_VOLUME
+                    && rightAmbient != INVALID_VOLUME) {
+                setVolumeIfValid(SIDE_LEFT, leftAmbient);
+                setVolumeIfValid(SIDE_RIGHT, rightAmbient);
+                setAmbientControlExpanded(true);
+            } else {
+                int unifiedAmbient = leftAmbient != INVALID_VOLUME ? leftAmbient : rightAmbient;
+                setVolumeIfValid(SIDE_UNIFIED, unifiedAmbient);
+            }
+        }
+        // Initialize local data between side and group value
+        initLocalAmbientDataIfNeeded();
+
+        // Update mute state
+        boolean mutable = true;
+        boolean muted = true;
+        if (isDeviceConnectedToVcp(leftDevice) && leftState != null) {
+            mutable &= leftState.isMutable();
+            muted &= leftState.isMuted();
+        }
+        if (isDeviceConnectedToVcp(rightDevice) && rightState != null) {
+            mutable &= rightState.isMutable();
+            muted &= rightState.isMuted();
+        }
+        mAmbientLayout.setMutable(mutable);
+        mAmbientLayout.setMuted(muted);
+
+        // Ensure remote device mute state is synced
+        syncMuteStateIfNeeded(leftDevice, leftState, muted);
+        syncMuteStateIfNeeded(rightDevice, rightState, muted);
+
+        updateSliderUi();
+    }
+
+    private void setAmbientControlExpanded(boolean expanded) {
+        mAmbientLayout.setExpanded(expanded);
+        mSideToDeviceMap.forEach((s, d) -> {
+            // Update new value to local data
+            mLocalDataManager.updateAmbientControlExpanded(d, expanded);
+        });
+        mLocalDataManager.flush();
+    }
+
+    /** Checks if any device in the same set has valid ambient control points */
+    private boolean isAmbientControlAvailable() {
+        for (BluetoothDevice device : mSideToDeviceMap.values()) {
+            if (mShowUiWhenLocalDataExist) {
+                // Found local ambient data
+                if (mLocalDataManager.get(device).hasAmbientData()) {
+                    return true;
+                }
+            }
+            // Found remote ambient control points
+            if (mVolumeController.isAmbientControlAvailable(device)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void initLocalAmbientDataIfNeeded() {
+        int smallerVolumeAmongGroup = Integer.MAX_VALUE;
+        for (BluetoothDevice device : mSideToDeviceMap.values()) {
+            HearingDeviceLocalDataManager.Data data = mLocalDataManager.get(device);
+            if (data.ambient() != INVALID_VOLUME) {
+                smallerVolumeAmongGroup = Math.min(data.ambient(), smallerVolumeAmongGroup);
+            } else if (data.groupAmbient() != INVALID_VOLUME) {
+                // Initialize side ambient from group ambient value
+                mLocalDataManager.updateAmbient(device, data.groupAmbient());
+            }
+        }
+        if (smallerVolumeAmongGroup != Integer.MAX_VALUE) {
+            for (BluetoothDevice device : mSideToDeviceMap.values()) {
+                HearingDeviceLocalDataManager.Data data = mLocalDataManager.get(device);
+                if (data.groupAmbient() == INVALID_VOLUME) {
+                    // Initialize group ambient from smaller side ambient value
+                    mLocalDataManager.updateGroupAmbient(device, smallerVolumeAmongGroup);
+                }
+            }
+        }
+        mLocalDataManager.flush();
+    }
+
+    private void syncMuteStateIfNeeded(@Nullable BluetoothDevice device,
+            @Nullable AmbientVolumeController.RemoteAmbientState state, boolean muted) {
+        if (isDeviceConnectedToVcp(device) && state != null && state.isMutable()) {
+            if (state.isMuted() != muted) {
+                mVolumeController.setMuted(device, muted);
+            }
+        }
+    }
+
+    private boolean isDeviceConnectedToVcp(@Nullable BluetoothDevice device) {
+        return device != null && device.isConnected()
+                && mProfileManager.getVolumeControlProfile().getConnectionStatus(device)
+                == BluetoothProfile.STATE_CONNECTED;
+    }
+
+    private void postOnMainThread(Runnable runnable) {
+        mContext.getMainThreadHandler().post(runnable);
+    }
+
+    private void postDelayedOnMainThread(Runnable runnable, long delay) {
+        mContext.getMainThreadHandler().postDelayed(runnable, delay);
+    }
+
+    private void showErrorToast(int stringResId) {
+        Toast.makeText(mContext, stringResId, Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 429e4c9..3c36c44 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -30,6 +30,7 @@
 import android.provider.DeviceConfig;
 import android.provider.MediaStore;
 import android.provider.Settings;
+import android.sysprop.BluetoothProperties;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -648,44 +649,55 @@
 
     /** Returns if the le audio sharing UI is available. */
     public static boolean isAudioSharingUIAvailable(@Nullable Context context) {
-        return isAudioSharingEnabled() || (context != null && isAudioSharingPreviewEnabled(
-                context.getContentResolver()));
+        return (Flags.enableLeAudioSharing()
+                || (context != null && Flags.audioSharingDeveloperOption()
+                && getAudioSharingPreviewValue(context.getContentResolver())))
+                && isAudioSharingSupported();
     }
 
     /** Returns if the le audio sharing hysteresis mode fix is available. */
     @WorkerThread
     public static boolean isAudioSharingHysteresisModeFixAvailable(@Nullable Context context) {
         return (audioSharingHysteresisModeFix() && Flags.enableLeAudioSharing())
-                || (context != null && isAudioSharingPreviewEnabled(context.getContentResolver()));
+                || (context != null && Flags.audioSharingDeveloperOption()
+                && getAudioSharingPreviewValue(context.getContentResolver()));
     }
 
     /** Returns if the le audio sharing is enabled. */
     public static boolean isAudioSharingEnabled() {
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        try {
-            return Flags.enableLeAudioSharing()
-                    && adapter.isLeAudioBroadcastSourceSupported()
-                            == BluetoothStatusCodes.FEATURE_SUPPORTED
-                    && adapter.isLeAudioBroadcastAssistantSupported()
-                            == BluetoothStatusCodes.FEATURE_SUPPORTED;
-        } catch (IllegalStateException e) {
-            Log.d(TAG, "Fail to check isAudioSharingEnabled, e = ", e);
-            return false;
-        }
+        return Flags.enableLeAudioSharing() && isAudioSharingSupported();
     }
 
     /** Returns if the le audio sharing preview is enabled in developer option. */
     public static boolean isAudioSharingPreviewEnabled(@Nullable ContentResolver contentResolver) {
+        return Flags.audioSharingDeveloperOption()
+                && getAudioSharingPreviewValue(contentResolver)
+                && isAudioSharingSupported();
+    }
+
+    /** Returns if the device has le audio sharing capability */
+    private static boolean isAudioSharingSupported() {
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         try {
-            return Flags.audioSharingDeveloperOption()
-                    && getAudioSharingPreviewValue(contentResolver)
-                    && adapter.isLeAudioBroadcastSourceSupported()
-                            == BluetoothStatusCodes.FEATURE_SUPPORTED
-                    && adapter.isLeAudioBroadcastAssistantSupported()
-                            == BluetoothStatusCodes.FEATURE_SUPPORTED;
+            // b/381777424 The APIs have to return ERROR_BLUETOOTH_NOT_ENABLED when BT off based on
+            // CDD definition.
+            // However, app layer need to gate the feature based on whether the device has audio
+            // sharing capability regardless of the BT state.
+            // So here we check the BluetoothProperties when BT off.
+            //
+            // TODO: Also check SystemProperties "persist.bluetooth.leaudio_dynamic_switcher.mode"
+            // and return true if it is in broadcast mode.
+            // Now SystemUI don't have access to read the value.
+            int sourceSupportedCode = adapter.isLeAudioBroadcastSourceSupported();
+            int assistantSupportedCode = adapter.isLeAudioBroadcastAssistantSupported();
+            return (sourceSupportedCode == BluetoothStatusCodes.FEATURE_SUPPORTED
+                    || (sourceSupportedCode == BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED
+                    && BluetoothProperties.isProfileBapBroadcastSourceEnabled().orElse(false)))
+                    && (assistantSupportedCode == BluetoothStatusCodes.FEATURE_SUPPORTED
+                    || (assistantSupportedCode == BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED
+                    && BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false)));
         } catch (IllegalStateException e) {
-            Log.d(TAG, "Fail to check isAudioSharingPreviewEnabled, e = ", e);
+            Log.d(TAG, "Fail to check isAudioSharingSupported, e = ", e);
             return false;
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManager.java
index 6725558..3cd3732 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManager.java
@@ -148,6 +148,14 @@
         }
     }
 
+    /** Flushes the data into Settings . */
+    public synchronized void flush() {
+        if (!mIsStarted) {
+            return;
+        }
+        putAmbientVolumeSettings();
+    }
+
     /**
      * Puts the local data of the corresponding hearing device.
      *
@@ -274,9 +282,6 @@
             notifyIfDataChanged(mAddrToDataMap, updatedAddrToDataMap);
             mAddrToDataMap.clear();
             mAddrToDataMap.putAll(updatedAddrToDataMap);
-            if (DEBUG) {
-                Log.v(TAG, "getLocalDataFromSettings, " + mAddrToDataMap + ", manager: " + this);
-            }
         }
     }
 
@@ -287,12 +292,10 @@
                 builder.append(KEY_ADDR).append("=").append(entry.getKey());
                 builder.append(entry.getValue().toSettingsFormat()).append(";");
             }
-            if (DEBUG) {
-                Log.v(TAG, "putAmbientVolumeSettings, " + builder + ", manager: " + this);
-            }
-            Settings.Global.putStringForUser(mContext.getContentResolver(),
-                    LOCAL_AMBIENT_VOLUME_SETTINGS, builder.toString(),
-                    UserHandle.USER_SYSTEM);
+            ThreadUtils.postOnBackgroundThread(() -> {
+                Settings.Global.putStringForUser(mContext.getContentResolver(),
+                        LOCAL_AMBIENT_VOLUME_SETTINGS, builder.toString(), UserHandle.USER_SYSTEM);
+            });
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
index b52ed42..7d5eece 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java
@@ -56,6 +56,7 @@
 import androidx.annotation.RequiresApi;
 
 import com.android.settingslib.R;
+import com.android.settingslib.flags.Flags;
 
 import com.google.common.collect.ImmutableList;
 
@@ -101,6 +102,7 @@
     public @interface BroadcastState {}
 
     private static final String SETTINGS_PKG = "com.android.settings";
+    private static final String SYSUI_PKG = "com.android.systemui";
     private static final String TAG = "LocalBluetoothLeBroadcast";
     private static final boolean DEBUG = BluetoothUtils.D;
 
@@ -216,6 +218,7 @@
                     }
                     setLatestBroadcastId(broadcastId);
                     setAppSourceName(mNewAppSourceName, /* updateContentResolver= */ true);
+                    notifyBroadcastStateChange(BROADCAST_STATE_ON);
                 }
 
                 @Override
@@ -232,7 +235,6 @@
                         Log.d(TAG, "onBroadcastMetadataChanged(), broadcastId = " + broadcastId);
                     }
                     setLatestBluetoothLeBroadcastMetadata(metadata);
-                    notifyBroadcastStateChange(BROADCAST_STATE_ON);
                 }
 
                 @Override
@@ -1125,6 +1127,10 @@
 
     /** Update fallback active device if needed. */
     public void updateFallbackActiveDeviceIfNeeded() {
+        if (Flags.disableAudioSharingAutoPickFallbackInUi()) {
+            Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded, disable flag is on");
+            return;
+        }
         if (isWorkProfile(mContext)) {
             Log.d(TAG, "Skip updateFallbackActiveDeviceIfNeeded for work profile.");
             return;
@@ -1247,8 +1253,9 @@
     }
 
     private void notifyBroadcastStateChange(@BroadcastState int state) {
-        if (!mContext.getPackageName().equals(SETTINGS_PKG)) {
-            Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered by Settings.");
+        String packageName = mContext.getPackageName();
+        if (!packageName.equals(SETTINGS_PKG) && !packageName.equals(SYSUI_PKG)) {
+            Log.d(TAG, "Skip notifyBroadcastStateChange, not triggered by Settings or SystemUI.");
             return;
         }
         if (isWorkProfile(mContext)) {
@@ -1257,8 +1264,8 @@
         }
         Intent intent = new Intent(ACTION_LE_AUDIO_SHARING_STATE_CHANGE);
         intent.putExtra(EXTRA_LE_AUDIO_SHARING_STATE, state);
-        intent.setPackage(mContext.getPackageName());
-        Log.d(TAG, "notifyBroadcastStateChange for state = " + state);
+        intent.setPackage(SETTINGS_PKG);
+        Log.d(TAG, "notifyBroadcastStateChange for state = " + state + " by pkg = " + packageName);
         mContext.sendBroadcast(intent);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index cf45231..c9aac91 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -21,6 +21,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.MainThread;
+import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -1643,7 +1644,7 @@
         CharSequence appLabel = "";
         ApplicationInfo appInfo = null;
         try {
-            int userId = UserHandle.getUserId(UserHandle.USER_CURRENT);
+            int userId = ActivityManager.getCurrentUser();
             appInfo = packageManager.getApplicationInfoAsUser(packageName, 0 /* flags */, userId);
         } catch (PackageManager.NameNotFoundException e) {
             Log.e(TAG, "Failed to get app info", e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
index e01f279..c71b19c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
@@ -501,7 +501,7 @@
                 val wifiManager = context.getSystemService(WifiManager::class.java) ?: return@launch
                 val aapmManager = context.getSystemService(AdvancedProtectionManager::class.java)
                 if (isAdvancedProtectionEnabled(aapmManager)) {
-                    val intent = aapmManager.createSupportIntent(
+                    val intent = AdvancedProtectionManager.createSupportIntent(
                         AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP,
                         AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION)
                     onStartActivity(intent)
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeUiControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeUiControllerTest.java
new file mode 100644
index 0000000..8b606e2
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/AmbientVolumeUiControllerTest.java
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static android.bluetooth.AudioInputControl.MUTE_DISABLED;
+import static android.bluetooth.AudioInputControl.MUTE_MUTED;
+import static android.bluetooth.AudioInputControl.MUTE_NOT_MUTED;
+import static android.bluetooth.BluetoothDevice.BOND_BONDED;
+
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/** Tests for {@link AmbientVolumeUiController}. */
+@RunWith(RobolectricTestRunner.class)
+public class AmbientVolumeUiControllerTest {
+
+    @Rule
+    public MockitoRule mockito = MockitoJUnit.rule();
+
+    private static final String TEST_ADDRESS = "00:00:00:00:11";
+    private static final String TEST_MEMBER_ADDRESS = "00:00:00:00:22";
+
+    @Mock
+    LocalBluetoothManager mBluetoothManager;
+    @Mock
+    LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    BluetoothEventManager mEventManager;
+    @Mock
+    VolumeControlProfile mVolumeControlProfile;
+    @Mock
+    AmbientVolumeUi mAmbientLayout;
+    @Mock
+    private AmbientVolumeController mVolumeController;
+    @Mock
+    private HearingDeviceLocalDataManager mLocalDataManager;
+    @Mock
+    private CachedBluetoothDevice mCachedDevice;
+    @Mock
+    private CachedBluetoothDevice mCachedMemberDevice;
+    @Mock
+    private BluetoothDevice mDevice;
+    @Mock
+    private BluetoothDevice mMemberDevice;
+    @Mock
+    private Handler mTestHandler;
+
+    @Spy
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+    private AmbientVolumeUiController mController;
+
+    @Before
+    public void setUp() {
+        when(mBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
+        when(mBluetoothManager.getEventManager()).thenReturn(mEventManager);
+
+        mController = spy(new AmbientVolumeUiController(mContext, mBluetoothManager,
+                mAmbientLayout, mVolumeController, mLocalDataManager));
+
+        when(mProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControlProfile);
+        when(mVolumeControlProfile.getConnectionStatus(mDevice)).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        when(mVolumeControlProfile.getConnectionStatus(mMemberDevice)).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        when(mVolumeController.isAmbientControlAvailable(mDevice)).thenReturn(true);
+        when(mVolumeController.isAmbientControlAvailable(mMemberDevice)).thenReturn(true);
+        when(mLocalDataManager.get(any(BluetoothDevice.class))).thenReturn(
+                new HearingDeviceLocalDataManager.Data.Builder().build());
+
+        when(mContext.getMainThreadHandler()).thenReturn(mTestHandler);
+        Answer<Object> answer = invocationOnMock -> {
+            invocationOnMock.getArgument(0, Runnable.class).run();
+            return null;
+        };
+        when(mTestHandler.post(any(Runnable.class))).thenAnswer(answer);
+        when(mTestHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(answer);
+
+        prepareDevice(/* hasMember= */ true);
+        mController.loadDevice(mCachedDevice);
+        Mockito.reset(mController);
+        Mockito.reset(mAmbientLayout);
+    }
+
+    @Test
+    public void loadDevice_deviceWithoutMember_controlNotExpandable() {
+        prepareDevice(/* hasMember= */ false);
+
+        mController.loadDevice(mCachedDevice);
+
+        verify(mAmbientLayout).setExpandable(false);
+    }
+
+    @Test
+    public void loadDevice_deviceWithMember_controlExpandable() {
+        prepareDevice(/* hasMember= */ true);
+
+        mController.loadDevice(mCachedDevice);
+
+        verify(mAmbientLayout).setExpandable(true);
+    }
+
+    @Test
+    public void loadDevice_deviceNotSupportVcp_ambientLayoutGone() {
+        when(mCachedDevice.getProfiles()).thenReturn(List.of());
+
+        mController.loadDevice(mCachedDevice);
+
+        verify(mAmbientLayout).setVisible(false);
+    }
+
+    @Test
+    public void loadDevice_ambientControlNotAvailable_ambientLayoutGone() {
+        when(mVolumeController.isAmbientControlAvailable(mDevice)).thenReturn(false);
+        when(mVolumeController.isAmbientControlAvailable(mMemberDevice)).thenReturn(false);
+
+        mController.loadDevice(mCachedDevice);
+
+        verify(mAmbientLayout).setVisible(false);
+    }
+
+    @Test
+    public void loadDevice_supportVcpAndAmbientControlAvailable_ambientLayoutVisible() {
+        when(mCachedDevice.getProfiles()).thenReturn(List.of(mVolumeControlProfile));
+        when(mVolumeController.isAmbientControlAvailable(mDevice)).thenReturn(true);
+
+        mController.loadDevice(mCachedDevice);
+
+        verify(mAmbientLayout).setVisible(true);
+    }
+
+    @Test
+    public void start_callbackRegistered() {
+        mController.start();
+
+        verify(mEventManager).registerCallback(mController);
+        verify(mLocalDataManager).start();
+        verify(mVolumeController).registerCallback(any(Executor.class), eq(mDevice));
+        verify(mVolumeController).registerCallback(any(Executor.class), eq(mMemberDevice));
+        verify(mCachedDevice).registerCallback(any(Executor.class),
+                any(CachedBluetoothDevice.Callback.class));
+        verify(mCachedMemberDevice).registerCallback(any(Executor.class),
+                any(CachedBluetoothDevice.Callback.class));
+    }
+
+    @Test
+    public void stop_callbackUnregistered() {
+        mController.stop();
+
+        verify(mEventManager).unregisterCallback(mController);
+        verify(mLocalDataManager).stop();
+        verify(mVolumeController).unregisterCallback(mDevice);
+        verify(mVolumeController).unregisterCallback(mMemberDevice);
+        verify(mCachedDevice).unregisterCallback(any(CachedBluetoothDevice.Callback.class));
+        verify(mCachedMemberDevice).unregisterCallback(any(CachedBluetoothDevice.Callback.class));
+    }
+
+    @Test
+    public void onDeviceLocalDataChange_verifySetExpandedAndDataUpdated() {
+        final boolean testExpanded = true;
+        HearingDeviceLocalDataManager.Data data = new HearingDeviceLocalDataManager.Data.Builder()
+                .ambient(0).groupAmbient(0).ambientControlExpanded(testExpanded).build();
+        when(mLocalDataManager.get(mDevice)).thenReturn(data);
+
+        mController.onDeviceLocalDataChange(TEST_ADDRESS, data);
+        shadowOf(Looper.getMainLooper()).idle();
+
+        verify(mAmbientLayout).setExpanded(testExpanded);
+        verifyDeviceDataUpdated(mDevice);
+    }
+
+    @Test
+    public void onAmbientChanged_refreshWhenNotInitiateFromUi() {
+        HearingDeviceLocalDataManager.Data data = new HearingDeviceLocalDataManager.Data.Builder()
+                .ambient(10).groupAmbient(10).ambientControlExpanded(true).build();
+        when(mLocalDataManager.get(mDevice)).thenReturn(data);
+        when(mAmbientLayout.isExpanded()).thenReturn(true);
+
+        mController.onAmbientChanged(mDevice, 10);
+        verify(mController, never()).refresh();
+
+        mController.onAmbientChanged(mDevice, 20);
+        verify(mController).refresh();
+    }
+
+    @Test
+    public void onMuteChanged_refreshWhenNotInitiateFromUi() {
+        AmbientVolumeController.RemoteAmbientState state =
+                new AmbientVolumeController.RemoteAmbientState(MUTE_NOT_MUTED, 0);
+        when(mVolumeController.refreshAmbientState(mDevice)).thenReturn(state);
+        when(mAmbientLayout.isExpanded()).thenReturn(false);
+
+        mController.onMuteChanged(mDevice, MUTE_NOT_MUTED);
+        verify(mController, never()).refresh();
+
+        mController.onMuteChanged(mDevice, MUTE_MUTED);
+        verify(mController).refresh();
+    }
+
+    @Test
+    public void refresh_leftAndRightDifferentGainSetting_expandControl() {
+        prepareRemoteData(mDevice, 10, MUTE_NOT_MUTED);
+        prepareRemoteData(mMemberDevice, 20, MUTE_NOT_MUTED);
+        when(mAmbientLayout.isExpanded()).thenReturn(false);
+
+        mController.refresh();
+
+        verify(mAmbientLayout).setExpanded(true);
+    }
+
+    @Test
+    public void refresh_oneSideNotMutable_controlNotMutableAndNotMuted() {
+        prepareRemoteData(mDevice, 10, MUTE_DISABLED);
+        prepareRemoteData(mMemberDevice, 20, MUTE_NOT_MUTED);
+
+        mController.refresh();
+
+        verify(mAmbientLayout).setMutable(false);
+        verify(mAmbientLayout).setMuted(false);
+    }
+
+    @Test
+    public void refresh_oneSideNotMuted_controlNotMutedAndSyncToRemote() {
+        prepareRemoteData(mDevice, 10, MUTE_MUTED);
+        prepareRemoteData(mMemberDevice, 20, MUTE_NOT_MUTED);
+
+        mController.refresh();
+
+        verify(mAmbientLayout).setMutable(true);
+        verify(mAmbientLayout).setMuted(false);
+        verify(mVolumeController).setMuted(mDevice, false);
+    }
+
+    private void prepareDevice(boolean hasMember) {
+        when(mCachedDevice.getDeviceSide()).thenReturn(SIDE_LEFT);
+        when(mCachedDevice.getDevice()).thenReturn(mDevice);
+        when(mCachedDevice.getBondState()).thenReturn(BOND_BONDED);
+        when(mCachedDevice.getProfiles()).thenReturn(List.of(mVolumeControlProfile));
+        when(mDevice.getAddress()).thenReturn(TEST_ADDRESS);
+        when(mDevice.getAnonymizedAddress()).thenReturn(TEST_ADDRESS);
+        when(mDevice.isConnected()).thenReturn(true);
+        if (hasMember) {
+            when(mCachedDevice.getMemberDevice()).thenReturn(Set.of(mCachedMemberDevice));
+            when(mCachedMemberDevice.getDeviceSide()).thenReturn(SIDE_RIGHT);
+            when(mCachedMemberDevice.getDevice()).thenReturn(mMemberDevice);
+            when(mCachedMemberDevice.getBondState()).thenReturn(BOND_BONDED);
+            when(mCachedMemberDevice.getProfiles()).thenReturn(List.of(mVolumeControlProfile));
+            when(mMemberDevice.getAddress()).thenReturn(TEST_MEMBER_ADDRESS);
+            when(mMemberDevice.getAnonymizedAddress()).thenReturn(TEST_MEMBER_ADDRESS);
+            when(mMemberDevice.isConnected()).thenReturn(true);
+        } else {
+            when(mCachedDevice.getMemberDevice()).thenReturn(Set.of());
+        }
+    }
+
+    private void prepareRemoteData(BluetoothDevice device, int gainSetting, int mute) {
+        when(mVolumeController.refreshAmbientState(device)).thenReturn(
+                new AmbientVolumeController.RemoteAmbientState(gainSetting, mute));
+    }
+
+    private void verifyDeviceDataUpdated(BluetoothDevice device) {
+        verify(mLocalDataManager).updateAmbient(eq(device), anyInt());
+        verify(mLocalDataManager).updateGroupAmbient(eq(device), anyInt());
+        verify(mLocalDataManager).updateAmbientControlExpanded(eq(device),
+                anyBoolean());
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 22b3150..b86f4b3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -309,6 +309,7 @@
 
     private void setUpAudioSharing(boolean enableFlag, boolean enableFeature,
             boolean enableProfile, boolean workProfile) {
+        mSetFlagsRule.disableFlags(Flags.FLAG_DISABLE_AUDIO_SHARING_AUTO_PICK_FALLBACK_IN_UI);
         if (enableFlag) {
             mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         } else {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index fa5d542..ab9f871 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -970,8 +970,10 @@
         when(cachedBluetoothDevice2.getGroupId()).thenReturn(2);
 
         BluetoothDevice device1 = mock(BluetoothDevice.class);
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(device1);
         when(mDeviceManager.findDevice(device1)).thenReturn(mCachedBluetoothDevice);
         BluetoothDevice device2 = mock(BluetoothDevice.class);
+        when(cachedBluetoothDevice2.getDevice()).thenReturn(device2);
         when(mDeviceManager.findDevice(device2)).thenReturn(cachedBluetoothDevice2);
 
         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1, device2));
@@ -991,8 +993,10 @@
         when(cachedBluetoothDevice2.getGroupId()).thenReturn(2);
 
         BluetoothDevice device1 = mock(BluetoothDevice.class);
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(device1);
         when(mDeviceManager.findDevice(device1)).thenReturn(mCachedBluetoothDevice);
         BluetoothDevice device2 = mock(BluetoothDevice.class);
+        when(cachedBluetoothDevice2.getDevice()).thenReturn(device2);
         when(mDeviceManager.findDevice(device2)).thenReturn(cachedBluetoothDevice2);
 
         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device1, device2));
@@ -1012,8 +1016,10 @@
         when(cachedBluetoothDevice2.getGroupId()).thenReturn(2);
 
         BluetoothDevice device1 = mock(BluetoothDevice.class);
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(device1);
         when(mDeviceManager.findDevice(device1)).thenReturn(mCachedBluetoothDevice);
         BluetoothDevice device2 = mock(BluetoothDevice.class);
+        when(cachedBluetoothDevice2.getDevice()).thenReturn(device2);
         when(mDeviceManager.findDevice(device2)).thenReturn(cachedBluetoothDevice2);
 
         when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(device2));
@@ -1035,10 +1041,13 @@
         when(cachedBluetoothDevice3.getGroupId()).thenReturn(3);
 
         BluetoothDevice device1 = mock(BluetoothDevice.class);
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(device1);
         when(mDeviceManager.findDevice(device1)).thenReturn(mCachedBluetoothDevice);
         BluetoothDevice device2 = mock(BluetoothDevice.class);
+        when(cachedBluetoothDevice2.getDevice()).thenReturn(device2);
         when(mDeviceManager.findDevice(device2)).thenReturn(cachedBluetoothDevice2);
         BluetoothDevice device3 = mock(BluetoothDevice.class);
+        when(cachedBluetoothDevice3.getDevice()).thenReturn(device3);
         when(mDeviceManager.findDevice(device3)).thenReturn(cachedBluetoothDevice3);
 
         when(mAssistant.getAllConnectedDevices())
@@ -1280,6 +1289,8 @@
         mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
         mSetFlagsRule.disableFlags(Flags.FLAG_AUDIO_SHARING_HYSTERESIS_MODE_FIX);
         mSetFlagsRule.enableFlags(Flags.FLAG_AUDIO_SHARING_DEVELOPER_OPTION);
+        Settings.Global.putInt(mContext.getContentResolver(),
+                BluetoothUtils.DEVELOPER_OPTION_PREVIEW_KEY, 1);
 
         assertThat(BluetoothUtils.isAudioSharingHysteresisModeFixAvailable(mContext)).isTrue();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManagerTest.java
index 6d83588..6485636 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingDeviceLocalDataManagerTest.java
@@ -31,6 +31,8 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.settingslib.utils.ThreadUtils;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -49,7 +51,10 @@
 
 /** Tests for {@link HearingDeviceLocalDataManager}. */
 @RunWith(RobolectricTestRunner.class)
-@Config(shadows = {HearingDeviceLocalDataManagerTest.ShadowGlobal.class})
+@Config(shadows = {
+        HearingDeviceLocalDataManagerTest.ShadowGlobal.class,
+        HearingDeviceLocalDataManagerTest.ShadowThreadUtils.class,
+})
 public class HearingDeviceLocalDataManagerTest {
 
     private static final String TEST_ADDRESS = "XX:XX:XX:XX:11:22";
@@ -249,4 +254,12 @@
             return sDataMap.computeIfAbsent(cr, k -> new HashMap<>());
         }
     }
+
+    @Implements(value = ThreadUtils.class)
+    public static class ShadowThreadUtils {
+        @Implementation
+        protected static void postOnBackgroundThread(Runnable runnable) {
+            runnable.run();
+        }
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
index 2b8b3b7..c939c77 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/SelectorWithWidgetPreferenceTest.java
@@ -21,9 +21,6 @@
 import static org.junit.Assert.assertEquals;
 
 import android.app.Application;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -33,10 +30,8 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settingslib.widget.preference.selector.R;
-import com.android.settingslib.widget.selectorwithwidgetpreference.flags.Flags;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.Robolectric;
@@ -45,7 +40,6 @@
 @RunWith(RobolectricTestRunner.class)
 public class SelectorWithWidgetPreferenceTest {
 
-    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
     private Application mContext;
     private SelectorWithWidgetPreference mPreference;
 
@@ -128,26 +122,6 @@
     }
 
     @Test
-    @DisableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES)
-    public void onBindViewHolder_titleMaxLinesSet_flagOff_titleMaxLinesMatchesDefault() {
-        final int titleMaxLines = 5;
-        AttributeSet attributeSet = Robolectric.buildAttributeSet()
-                .addAttribute(R.attr.titleMaxLines, String.valueOf(titleMaxLines))
-                .build();
-        mPreference = new SelectorWithWidgetPreference(mContext, attributeSet);
-        View view = LayoutInflater.from(mContext)
-                .inflate(mPreference.getLayoutResource(), null /* root */);
-        PreferenceViewHolder preferenceViewHolder =
-                PreferenceViewHolder.createInstanceForTests(view);
-
-        mPreference.onBindViewHolder(preferenceViewHolder);
-
-        TextView title = (TextView) preferenceViewHolder.findViewById(android.R.id.title);
-        assertThat(title.getMaxLines()).isEqualTo(SelectorWithWidgetPreference.DEFAULT_MAX_LINES);
-    }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES)
     public void onBindViewHolder_noTitleMaxLinesSet_titleMaxLinesMatchesDefault() {
         AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
         mPreference = new SelectorWithWidgetPreference(mContext, attributeSet);
@@ -163,7 +137,6 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_ALLOW_SET_TITLE_MAX_LINES)
     public void onBindViewHolder_titleMaxLinesSet_titleMaxLinesUpdated() {
         final int titleMaxLines = 5;
         AttributeSet attributeSet = Robolectric.buildAttributeSet()
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 935ea25..f1bbfc6 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -108,6 +108,7 @@
                 Settings.System.AUTO_LAUNCH_MEDIA_CONTROLS,
                 Settings.System.LOCALE_PREFERENCES,
                 Settings.System.MOUSE_REVERSE_VERTICAL_SCROLLING,
+                Settings.System.MOUSE_SCROLLING_ACCELERATION,
                 Settings.System.MOUSE_SWAP_PRIMARY_BUTTON,
                 Settings.System.TOUCHPAD_POINTER_SPEED,
                 Settings.System.TOUCHPAD_NATURAL_SCROLLING,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 63f401c..6abd9b7 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -225,6 +225,7 @@
                 new InclusiveFloatRangeValidator(DEFAULT_POINTER_SCALE, LARGE_POINTER_SCALE));
         VALIDATORS.put(System.MOUSE_REVERSE_VERTICAL_SCROLLING, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.MOUSE_SWAP_PRIMARY_BUTTON, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.MOUSE_SCROLLING_ACCELERATION, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.TOUCHPAD_POINTER_SPEED, new InclusiveIntegerRangeValidator(-7, 7));
         VALIDATORS.put(System.TOUCHPAD_NATURAL_SCROLLING, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.TOUCHPAD_TAP_TO_CLICK, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 91ac34a..de7c450 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -148,27 +148,7 @@
             // TODO(b/364399200): use filter to skip instead?
             return;
         }
-
-        ArrayList<String> missingFiles = new ArrayList<String>();
-        for (String fileName : sAconfigTextProtoFilesOnDevice) {
-            File aconfigFile = new File(fileName);
-            if (!aconfigFile.exists()) {
-                missingFiles.add(fileName);
-            }
-        }
-
-        if (missingFiles.isEmpty()) {
-            pw.println("\nAconfig flags:");
-            for (String name : MyShellCommand.listAllAconfigFlags(iprovider)) {
-                pw.println(name);
-            }
-        } else {
-            pw.println("\nFailed to dump aconfig flags due to missing files:");
-            for (String fileName : missingFiles) {
-                pw.println(fileName);
-            }
-        }
-    }
+   }
 
     private static HashSet<String> getAconfigFlagNamesInDeviceConfig() {
         HashSet<String> nameSet = new HashSet<String>();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 1c4def3..a2cc008 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -16,6 +16,19 @@
 
 package com.android.providers.settings;
 
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_DEVICE_SPECIFIC_CONFIG;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_GLOBAL;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_LOCALE;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_LOCK_SETTINGS;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_NETWORK_POLICIES;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SECURE;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SIM_SPECIFIC_SETTINGS;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SIM_SPECIFIC_SETTINGS_2;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SOFTAP_CONFIG;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_SYSTEM;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_WIFI_NEW_CONFIG;
+import static com.android.providers.settings.SettingsBackupRestoreKeys.KEY_WIFI_SETTINGS_BACKUP_DATA;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -99,22 +112,6 @@
     private static final int NULL_SIZE = -1;
     private static final float FONT_SCALE_DEF_VALUE = 1.0f;
 
-    private static final String KEY_SYSTEM = "system";
-    private static final String KEY_SECURE = "secure";
-    private static final String KEY_GLOBAL = "global";
-    private static final String KEY_LOCALE = "locale";
-    private static final String KEY_LOCK_SETTINGS = "lock_settings";
-    private static final String KEY_SOFTAP_CONFIG = "softap_config";
-    private static final String KEY_NETWORK_POLICIES = "network_policies";
-    private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config";
-    private static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config";
-    private static final String KEY_SIM_SPECIFIC_SETTINGS = "sim_specific_settings";
-    // Restoring sim-specific data backed up from newer Android version to Android 12 was causing a
-    // fatal crash. Creating a backup with a different key will prevent Android 12 versions from
-    // restoring this data.
-    private static final String KEY_SIM_SPECIFIC_SETTINGS_2 = "sim_specific_settings_2";
-    private static final String KEY_WIFI_SETTINGS_BACKUP_DATA = "wifi_settings_backup_data";
-
     // Versioning of the state file.  Increment this version
     // number any time the set of state items is altered.
     private static final int STATE_VERSION = 9;
@@ -257,6 +254,7 @@
         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
         if (com.android.server.backup.Flags.enableMetricsSettingsBackupAgents()) {
             mBackupRestoreEventLogger = this.getBackupRestoreEventLogger();
+            mSettingsHelper.setBackupRestoreEventLogger(mBackupRestoreEventLogger);
             numberOfSettingsPerKey = new HashMap<>();
             areAgentMetricsEnabled = true;
         }
@@ -412,9 +410,7 @@
                     mSettingsHelper
                         .setLocaleData(
                             localeData,
-                            size,
-                            mBackupRestoreEventLogger,
-                            KEY_LOCALE);
+                            size);
                     break;
 
                 case KEY_WIFI_CONFIG :
@@ -552,8 +548,7 @@
             if (nBytes > buffer.length) buffer = new byte[nBytes];
             in.readFully(buffer, 0, nBytes);
             mSettingsHelper
-                .setLocaleData(
-                    buffer, nBytes, mBackupRestoreEventLogger, KEY_LOCALE);
+                .setLocaleData(buffer, nBytes);
 
             // Restore older backups performing the necessary migrations.
             if (version < FULL_BACKUP_ADDED_WIFI_NEW) {
@@ -1058,14 +1053,10 @@
                 Log.d(TAG, "Restored font scale from: " + toRestore + " to " + value);
             }
 
-            // TODO(b/379861078): Log metrics inside this method.
             settingsHelper.restoreValue(this, cr, contentValues, destination, key, value,
                     mRestoredFromSdkInt);
 
             Log.d(TAG, "Restored setting: " + destination + " : " + key + "=" + value);
-            if (areAgentMetricsEnabled) {
-                mBackupRestoreEventLogger.logItemsRestored(finalSettingsKey, /* count= */ 1);
-            }
         }
 
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupRestoreKeys.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupRestoreKeys.java
new file mode 100644
index 0000000..745c2fb
--- /dev/null
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupRestoreKeys.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import android.net.Uri;
+import android.provider.Settings;
+
+/**
+ * Class to store the keys used for backup and restore.
+ */
+final class SettingsBackupRestoreKeys {
+    static final String KEY_UNKNOWN = "unknown";
+    static final String KEY_SYSTEM = "system";
+    static final String KEY_SECURE = "secure";
+    static final String KEY_GLOBAL = "global";
+    static final String KEY_LOCALE = "locale";
+    static final String KEY_LOCK_SETTINGS = "lock_settings";
+    static final String KEY_SOFTAP_CONFIG = "softap_config";
+    static final String KEY_NETWORK_POLICIES = "network_policies";
+    static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config";
+    static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config";
+    static final String KEY_SIM_SPECIFIC_SETTINGS = "sim_specific_settings";
+    // Restoring sim-specific data backed up from newer Android version to Android 12 was causing a
+    // fatal crash. Creating a backup with a different key will prevent Android 12 versions from
+    // restoring this data.
+    static final String KEY_SIM_SPECIFIC_SETTINGS_2 = "sim_specific_settings_2";
+    static final String KEY_WIFI_SETTINGS_BACKUP_DATA = "wifi_settings_backup_data";
+
+    /**
+     * Returns the key corresponding to the given URI.
+     *
+     * @param uri The URI of the setting's destination.
+     * @return The key corresponding to the given URI, or KEY_UNKNOWN if the URI is not recognized.
+     */
+    static String getKeyFromUri(Uri uri) {
+      if (uri.equals(Settings.Secure.CONTENT_URI)) {
+        return KEY_SECURE;
+      } else if (uri.equals(Settings.System.CONTENT_URI)) {
+        return KEY_SYSTEM;
+      } else if (uri.equals(Settings.Global.CONTENT_URI)) {
+        return KEY_GLOBAL;
+      } else {
+        return KEY_UNKNOWN;
+      }
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 924c151..4f52031 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -17,6 +17,7 @@
 package com.android.providers.settings;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.app.backup.BackupRestoreEventLogger;
@@ -80,10 +81,12 @@
     // Error messages for logging metrics.
     private static final String ERROR_REMOTE_EXCEPTION_SETTING_LOCALE_DATA =
         "remote_exception_setting_locale_data";
+    private static final String ERROR_FAILED_TO_RESTORE_SETTING = "failed_to_restore_setting";
 
     private Context mContext;
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager;
+    @Nullable private BackupRestoreEventLogger mBackupRestoreEventLogger;
 
     /**
      * A few settings elements are special in that a restore of those values needs to
@@ -204,6 +207,12 @@
             table = sGlobalLookup;
         }
 
+        // Get datatype for B&R metrics logging.
+        String datatype = "";
+        if (Flags.enableMetricsSettingsBackupAgents()) {
+            datatype = SettingsBackupRestoreKeys.getKeyFromUri(destination);
+        }
+
         sendBroadcast = sBroadcastOnRestore.contains(name);
         sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name);
         sendBroadcastAccessibility = sBroadcastOnRestoreAccessibility.contains(name);
@@ -290,12 +299,19 @@
             contentValues.put(Settings.NameValueTable.NAME, name);
             contentValues.put(Settings.NameValueTable.VALUE, value);
             cr.insert(destination, contentValues);
+            if (Flags.enableMetricsSettingsBackupAgents()) {
+                mBackupRestoreEventLogger.logItemsRestored(datatype, /* count= */ 1);
+            }
         } catch (Exception e) {
             // If we fail to apply the setting, by definition nothing happened
             sendBroadcast = false;
             sendBroadcastSystemUI = false;
             sendBroadcastAccessibility = false;
             Log.e(TAG, "Failed to restore setting name: " + name + " + value: " + value, e);
+            if (Flags.enableMetricsSettingsBackupAgents()) {
+                mBackupRestoreEventLogger.logItemsRestoreFailed(
+                    datatype, /* count= */ 1, ERROR_FAILED_TO_RESTORE_SETTING);
+            }
         } finally {
             // If this was an element of interest, send the "we just restored it"
             // broadcast with the historical value now that the new value has
@@ -741,11 +757,8 @@
      *
      * @param data the comma separated BCP-47 language tags in bytes.
      * @param size the size of the data in bytes.
-     * @param backupRestoreEventLogger the logger to log the restore event.
-     * @param dataType the data type of the setting for logging purposes.
      */
-    /* package */ void setLocaleData(
-        byte[] data, int size, BackupRestoreEventLogger backupRestoreEventLogger, String dataType) {
+    /* package */ void setLocaleData(byte[] data, int size) {
         final Configuration conf = mContext.getResources().getConfiguration();
 
         // Replace "_" with "-" to deal with older backups.
@@ -772,15 +785,15 @@
 
             am.updatePersistentConfigurationWithAttribution(config, mContext.getOpPackageName(),
                     mContext.getAttributionTag());
-            if (Flags.enableMetricsSettingsBackupAgents()) {
-                backupRestoreEventLogger
-                    .logItemsRestored(dataType, localeList.size());
+            if (Flags.enableMetricsSettingsBackupAgents() && mBackupRestoreEventLogger != null) {
+                mBackupRestoreEventLogger
+                    .logItemsRestored(SettingsBackupRestoreKeys.KEY_LOCALE, localeList.size());
             }
         } catch (RemoteException e) {
-            if (Flags.enableMetricsSettingsBackupAgents()) {
-                backupRestoreEventLogger
+            if (Flags.enableMetricsSettingsBackupAgents() && mBackupRestoreEventLogger != null) {
+                mBackupRestoreEventLogger
                     .logItemsRestoreFailed(
-                        dataType,
+                        SettingsBackupRestoreKeys.KEY_LOCALE,
                         localeList.size(),
                         ERROR_REMOTE_EXCEPTION_SETTING_LOCALE_DATA);
             }
@@ -795,4 +808,13 @@
         AudioManager am = new AudioManager(mContext);
         am.reloadAudioSettings();
     }
+
+    /**
+     * Sets the backup restore event logger.
+     *
+     * @param backupRestoreEventLogger the logger to log B&R metrics.
+     */
+    void setBackupRestoreEventLogger(BackupRestoreEventLogger backupRestoreEventLogger) {
+        mBackupRestoreEventLogger = backupRestoreEventLogger;
+    }
 }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index f9c6442..661a095 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2520,6 +2520,13 @@
                 Settings.Secure.RTT_CALLING_MODE,
                 SecureSettingsProto.RTT_CALLING_MODE);
 
+        final long screenoffudfpsenabledToken = p.start(
+                SecureSettingsProto.SCREEN_OFF_UDFPS_ENABLED);
+        dumpSetting(s, p,
+                Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
+                SecureSettingsProto.SCREEN_OFF_UDFPS_ENABLED);
+        p.end(screenoffudfpsenabledToken);
+
         final long screensaverToken = p.start(SecureSettingsProto.SCREENSAVER);
         dumpSetting(s, p,
                 Settings.Secure.SCREENSAVER_ENABLED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 55f48e3..f1f03c3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -120,6 +120,7 @@
 
 import com.android.internal.accessibility.util.AccessibilityUtils;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.display.RefreshRateSettingsUtils;
 import com.android.internal.os.BackgroundThread;
@@ -2914,6 +2915,14 @@
         };
     }
 
+    @VisibleForTesting
+    void injectServices(UserManager userManager, IPackageManager packageManager,
+            SystemConfigManager sysConfigManager) {
+        mUserManager = userManager;
+        mPackageManager = packageManager;
+        mSysConfigManager = sysConfigManager;
+    }
+
     private static final class Arguments {
         private static final Pattern WHERE_PATTERN_WITH_PARAM_NO_BRACKETS =
                 Pattern.compile("[\\s]*name[\\s]*=[\\s]*\\?[\\s]*");
@@ -3080,6 +3089,7 @@
 
         private static final String SSAID_USER_KEY = "userkey";
 
+        @GuardedBy("mLock")
         private final SparseArray<SettingsState> mSettingsStates = new SparseArray<>();
 
         private GenerationRegistry mGenerationRegistry;
@@ -3992,6 +4002,14 @@
             }
         }
 
+        @VisibleForTesting
+        void injectSettings(SettingsState settings, int type, int userId) {
+            int key = makeKey(type, userId);
+            synchronized (mLock) {
+                mSettingsStates.put(key, settings);
+            }
+        }
+
         private final class MyHandler extends Handler {
             private static final int MSG_NOTIFY_URI_CHANGED = 1;
             private static final int MSG_NOTIFY_DATA_CHANGED = 2;
@@ -4023,12 +4041,21 @@
             }
         }
 
-        private final class UpgradeController {
+        @VisibleForTesting
+        final class UpgradeController {
             private static final int SETTINGS_VERSION = 226;
 
             private final int mUserId;
 
+            private final Injector mInjector;
+
             public UpgradeController(int userId) {
+                this(/* injector= */ null, userId);
+            }
+
+            @VisibleForTesting
+            UpgradeController(Injector injector, int userId) {
+                mInjector = injector == null ? new Injector() : injector;
                 mUserId = userId;
             }
 
@@ -6136,8 +6163,8 @@
                             systemSettings.getSettingLocked(Settings.System.PEAK_REFRESH_RATE);
                     final Setting minRefreshRateSetting =
                             systemSettings.getSettingLocked(Settings.System.MIN_REFRESH_RATE);
-                    float highestRefreshRate = RefreshRateSettingsUtils
-                            .findHighestRefreshRateForDefaultDisplay(getContext());
+                    float highestRefreshRate =
+                            mInjector.findHighestRefreshRateForDefaultDisplay(getContext());
 
                     if (!peakRefreshRateSetting.isNull()) {
                         try {
@@ -6318,6 +6345,14 @@
             private long getBitMask(int capability) {
                 return 1 << (capability - 1);
             }
+
+            @VisibleForTesting
+            static class Injector {
+                float findHighestRefreshRateForDefaultDisplay(Context context) {
+                    return RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(
+                            context);
+                }
+            }
         }
 
         /**
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 5cd534e..bf3afed 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -107,7 +107,7 @@
  * the same lock to grab the current state to write to disk.
  * </p>
  */
-final class SettingsState {
+public class SettingsState {
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_PERSISTENCE = false;
 
@@ -1838,7 +1838,7 @@
         }
     }
 
-    class Setting {
+    public class Setting {
         private String name;
         private String value;
         private String defaultValue;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index 350c149..18c43a7 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -422,75 +422,6 @@
 
     @Test
     @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
-    public void restoreSettings_agentMetricsAreEnabled_agentMetricsAreLogged() {
-        mAgentUnderTest.onCreate(
-            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
-        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
-                new SettingsBackupAgent.SettingsBackupAllowlist(
-                        new String[] {OVERRIDDEN_TEST_SETTING},
-                        TEST_VALUES_VALIDATORS);
-        mAgentUnderTest.setSettingsAllowlist(allowlist);
-        mAgentUnderTest.setBlockedSettings();
-        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
-        mAgentUnderTest.mSettingsHelper = settingsHelper;
-
-        byte[] backupData = generateBackupData(TEST_VALUES);
-        mAgentUnderTest
-            .restoreSettings(
-                backupData,
-                /* pos= */ 0,
-                backupData.length,
-                TEST_URI,
-                /* movedToGlobal= */ null,
-                /* movedToSecure= */ null,
-                /* movedToSystem= */ null,
-                /* blockedSettingsArrayId= */ 0,
-                /* dynamicBlockList= */ Collections.emptySet(),
-                /* settingsToPreserve= */ Collections.emptySet(),
-                TEST_KEY);
-
-        DataTypeResult loggingResult =
-            getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest);
-        assertNotNull(loggingResult);
-        assertEquals(loggingResult.getSuccessCount(), 1);
-    }
-
-    @Test
-    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
-    public void restoreSettings_agentMetricsAreDisabled_agentMetricsAreNotLogged() {
-        mAgentUnderTest.onCreate(
-            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
-        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
-                new SettingsBackupAgent.SettingsBackupAllowlist(
-                        new String[] {OVERRIDDEN_TEST_SETTING},
-                        TEST_VALUES_VALIDATORS);
-        mAgentUnderTest.setSettingsAllowlist(allowlist);
-        mAgentUnderTest.setBlockedSettings();
-        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
-        mAgentUnderTest.mSettingsHelper = settingsHelper;
-
-        byte[] backupData = generateBackupData(TEST_VALUES);
-        mAgentUnderTest
-            .restoreSettings(
-                backupData,
-                /* pos= */ 0,
-                backupData.length,
-                TEST_URI,
-                /* movedToGlobal= */ null,
-                /* movedToSecure= */ null,
-                /* movedToSystem= */ null,
-                /* blockedSettingsArrayId= */ 0,
-                /* dynamicBlockList= */ Collections.emptySet(),
-                /* settingsToPreserve= */ Collections.emptySet(),
-                TEST_KEY);
-
-        DataTypeResult loggingResult =
-            getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest);
-        assertNull(loggingResult);
-    }
-
-    @Test
-    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
     public void restoreSettings_agentMetricsAreEnabled_readEntityDataFails_failureIsLogged()
         throws IOException {
         when(mBackupDataInput.readEntityData(any(byte[].class), anyInt(), anyInt()))
@@ -577,6 +508,40 @@
     }
 
     @Test
+    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void
+        restoreSettings_agentMetricsAreDisabled_settingIsSkippedBySystem_failureIsNotLogged() {
+        mAgentUnderTest.onCreate(
+            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+        String[] settingBlockedBySystem = new String[] {OVERRIDDEN_TEST_SETTING};
+        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
+                new SettingsBackupAgent.SettingsBackupAllowlist(
+                        settingBlockedBySystem,
+                        TEST_VALUES_VALIDATORS);
+        mAgentUnderTest.setSettingsAllowlist(allowlist);
+        mAgentUnderTest.setBlockedSettings(settingBlockedBySystem);
+        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
+        mAgentUnderTest.mSettingsHelper = settingsHelper;
+
+        byte[] backupData = generateBackupData(TEST_VALUES);
+        mAgentUnderTest
+            .restoreSettings(
+                backupData,
+                /* pos= */ 0,
+                backupData.length,
+                TEST_URI,
+                /* movedToGlobal= */ null,
+                /* movedToSecure= */ null,
+                /* movedToSystem= */ null,
+                /* blockedSettingsArrayId= */ 0,
+                /* dynamicBlockList= */ Collections.emptySet(),
+                /* settingsToPreserve= */ Collections.emptySet(),
+                TEST_KEY);
+
+        assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
+    }
+
+    @Test
     @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
     public void restoreSettings_agentMetricsAreEnabled_settingIsSkippedByBlockList_failureIsLogged() {
         mAgentUnderTest.onCreate(
@@ -615,6 +580,41 @@
     }
 
     @Test
+    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void
+        restoreSettings_agentMetricsAreDisabled_settingIsSkippedByBlockList_failureIsNotLogged() {
+        mAgentUnderTest.onCreate(
+            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
+                new SettingsBackupAgent.SettingsBackupAllowlist(
+                        new String[] {OVERRIDDEN_TEST_SETTING},
+                        TEST_VALUES_VALIDATORS);
+        mAgentUnderTest.setSettingsAllowlist(allowlist);
+        mAgentUnderTest.setBlockedSettings();
+        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
+        mAgentUnderTest.mSettingsHelper = settingsHelper;
+        Set<String> dynamicBlockList =
+            Set.of(Uri.withAppendedPath(TEST_URI, OVERRIDDEN_TEST_SETTING).toString());
+
+        byte[] backupData = generateBackupData(TEST_VALUES);
+        mAgentUnderTest
+            .restoreSettings(
+                backupData,
+                /* pos= */ 0,
+                backupData.length,
+                TEST_URI,
+                /* movedToGlobal= */ null,
+                /* movedToSecure= */ null,
+                /* movedToSystem= */ null,
+                /* blockedSettingsArrayId= */ 0,
+                dynamicBlockList,
+                /* settingsToPreserve= */ Collections.emptySet(),
+                TEST_KEY);
+
+        assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
+    }
+
+    @Test
     @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
     public void restoreSettings_agentMetricsAreEnabled_settingIsPreserved_failureIsLogged() {
         mAgentUnderTest.onCreate(
@@ -653,6 +653,40 @@
     }
 
     @Test
+    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void restoreSettings_agentMetricsAreDisabled_settingIsPreserved_failureIsNotLogged() {
+        mAgentUnderTest.onCreate(
+            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
+        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
+                new SettingsBackupAgent.SettingsBackupAllowlist(
+                        new String[] {OVERRIDDEN_TEST_SETTING},
+                        TEST_VALUES_VALIDATORS);
+        mAgentUnderTest.setSettingsAllowlist(allowlist);
+        mAgentUnderTest.setBlockedSettings();
+        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
+        mAgentUnderTest.mSettingsHelper = settingsHelper;
+        Set<String> preservedSettings =
+            Set.of(Uri.withAppendedPath(TEST_URI, OVERRIDDEN_TEST_SETTING).toString());
+
+        byte[] backupData = generateBackupData(TEST_VALUES);
+        mAgentUnderTest
+            .restoreSettings(
+                backupData,
+                /* pos= */ 0,
+                backupData.length,
+                TEST_URI,
+                /* movedToGlobal= */ null,
+                /* movedToSecure= */ null,
+                /* movedToSystem= */ null,
+                /* blockedSettingsArrayId= */ 0,
+                /* dynamicBlockList = */ Collections.emptySet(),
+                preservedSettings,
+                TEST_KEY);
+
+        assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
+    }
+
+    @Test
     @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
     public void restoreSettings_agentMetricsAreEnabled_settingIsNotValid_failureIsLogged() {
         mAgentUnderTest.onCreate(
@@ -689,86 +723,14 @@
     }
 
     @Test
-    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
-    public void restoreSettings_agentMetricsAreEnabled_settingIsMarkedAsMovedToGlobal_agentMetricsAreLoggedWithGlobalKey() {
+    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void restoreSettings_agentMetricsAreDisabled_settingIsNotValid_failureIsNotLogged() {
         mAgentUnderTest.onCreate(
             UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
         SettingsBackupAgent.SettingsBackupAllowlist allowlist =
                 new SettingsBackupAgent.SettingsBackupAllowlist(
                         new String[] {OVERRIDDEN_TEST_SETTING},
-                        TEST_VALUES_VALIDATORS);
-        mAgentUnderTest.setSettingsAllowlist(allowlist);
-        mAgentUnderTest.setBlockedSettings();
-        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
-        mAgentUnderTest.mSettingsHelper = settingsHelper;
-
-        byte[] backupData = generateBackupData(TEST_VALUES);
-        mAgentUnderTest
-            .restoreSettings(
-                backupData,
-                /* pos= */ 0,
-                backupData.length,
-                TEST_URI,
-                /* movedToGlobal= */ Set.of(OVERRIDDEN_TEST_SETTING),
-                /* movedToSecure= */ null,
-                /* movedToSystem= */ null,
-                /* blockedSettingsArrayId= */ 0,
-                /* dynamicBlockList= */ Collections.emptySet(),
-                /* settingsToPreserve= */ Collections.emptySet(),
-                TEST_KEY);
-
-        DataTypeResult loggingResult =
-            getLoggingResultForDatatype(KEY_GLOBAL, mAgentUnderTest);
-        assertNotNull(loggingResult);
-        assertEquals(loggingResult.getSuccessCount(), 1);
-        assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
-    }
-
-    @Test
-    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
-    public void restoreSettings_agentMetricsAreEnabled_settingIsMarkedAsMovedToSecure_agentMetricsAreLoggedWithSecureKey() {
-        mAgentUnderTest.onCreate(
-            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
-        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
-                new SettingsBackupAgent.SettingsBackupAllowlist(
-                        new String[] {OVERRIDDEN_TEST_SETTING},
-                        TEST_VALUES_VALIDATORS);
-        mAgentUnderTest.setSettingsAllowlist(allowlist);
-        mAgentUnderTest.setBlockedSettings();
-        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
-        mAgentUnderTest.mSettingsHelper = settingsHelper;
-
-        byte[] backupData = generateBackupData(TEST_VALUES);
-        mAgentUnderTest
-            .restoreSettings(
-                backupData,
-                /* pos= */ 0,
-                backupData.length,
-                TEST_URI,
-                /* movedToGlobal= */ null,
-                /* movedToSecure= */ Set.of(OVERRIDDEN_TEST_SETTING),
-                /* movedToSystem= */ null,
-                /* blockedSettingsArrayId= */ 0,
-                /* dynamicBlockList= */ Collections.emptySet(),
-                /* settingsToPreserve= */ Collections.emptySet(),
-                TEST_KEY);
-
-        DataTypeResult loggingResult =
-            getLoggingResultForDatatype(KEY_SECURE, mAgentUnderTest);
-        assertNotNull(loggingResult);
-        assertEquals(loggingResult.getSuccessCount(), 1);
-        assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
-    }
-
-    @Test
-    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
-    public void restoreSettings_agentMetricsAreEnabled_settingIsMarkedAsMovedToSystem_agentMetricsAreLoggedWithSystemKey() {
-        mAgentUnderTest.onCreate(
-            UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE);
-        SettingsBackupAgent.SettingsBackupAllowlist allowlist =
-                new SettingsBackupAgent.SettingsBackupAllowlist(
-                        new String[] {OVERRIDDEN_TEST_SETTING},
-                        TEST_VALUES_VALIDATORS);
+                        /* settingsValidators= */ null);
         mAgentUnderTest.setSettingsAllowlist(allowlist);
         mAgentUnderTest.setBlockedSettings();
         TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
@@ -783,16 +745,12 @@
                 TEST_URI,
                 /* movedToGlobal= */ null,
                 /* movedToSecure= */ null,
-                /* movedToSystem= */ Set.of(OVERRIDDEN_TEST_SETTING),
+                /* movedToSystem= */ null,
                 /* blockedSettingsArrayId= */ 0,
-                /* dynamicBlockList= */ Collections.emptySet(),
+                /* dynamicBlockList = */ Collections.emptySet(),
                 /* settingsToPreserve= */ Collections.emptySet(),
                 TEST_KEY);
 
-        DataTypeResult loggingResult =
-            getLoggingResultForDatatype(KEY_SYSTEM, mAgentUnderTest);
-        assertNotNull(loggingResult);
-        assertEquals(loggingResult.getSuccessCount(), 1);
         assertNull(getLoggingResultForDatatype(TEST_KEY, mAgentUnderTest));
     }
 
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupRestoreKeysTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupRestoreKeysTest.java
new file mode 100644
index 0000000..ef537e8
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupRestoreKeysTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SettingsBackupRestoreKeys}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SettingsBackupRestoreKeysTest {
+
+    @Test
+    public void getKeyFromUri_secureUri_returnsSecureKey() {
+        assertThat(SettingsBackupRestoreKeys.getKeyFromUri(Settings.Secure.CONTENT_URI))
+                .isEqualTo(SettingsBackupRestoreKeys.KEY_SECURE);
+    }
+
+    @Test
+    public void getKeyFromUri_systemUri_returnsSystemKey() {
+        assertThat(SettingsBackupRestoreKeys.getKeyFromUri(Settings.System.CONTENT_URI))
+                .isEqualTo(SettingsBackupRestoreKeys.KEY_SYSTEM);
+    }
+
+    @Test
+    public void getKeyFromUri_globalUri_returnsGlobalKey() {
+        assertThat(SettingsBackupRestoreKeys.getKeyFromUri(Settings.Global.CONTENT_URI))
+                .isEqualTo(SettingsBackupRestoreKeys.KEY_GLOBAL);
+    }
+
+    @Test
+    public void getKeyFromUri_unknownUri_returnsUnknownKey() {
+        assertThat(SettingsBackupRestoreKeys.getKeyFromUri(Uri.parse("content://unknown")))
+                .isEqualTo(SettingsBackupRestoreKeys.KEY_UNKNOWN);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
index 58200d4..40654b0 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java
@@ -28,6 +28,9 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import android.app.backup.BackupAnnotations.OperationType;
+import android.app.backup.BackupRestoreEventLogger;
+import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.Context;
@@ -42,6 +45,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.LocaleList;
+import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.BaseColumns;
@@ -65,6 +69,8 @@
 import org.junit.runners.MethodSorters;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Tests for the SettingsHelperTest
@@ -91,6 +97,8 @@
 
     @Rule
     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
 
     @Mock private Context mContext;
     @Mock private Resources mResources;
@@ -100,6 +108,8 @@
     @Mock private MockContentResolver mContentResolver;
     private MockSettingsProvider mSettingsProvider;
 
+    private BackupRestoreEventLogger mBackupRestoreEventLogger;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -115,6 +125,8 @@
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
         mSettingsProvider = new MockSettingsProvider(mContext);
         mContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
+        mBackupRestoreEventLogger = new BackupRestoreEventLogger(OperationType.RESTORE);
+        mSettingsHelper.setBackupRestoreEventLogger(mBackupRestoreEventLogger);
     }
 
     @After
@@ -791,6 +803,99 @@
         assertThat(mSettingsHelper.getLocaleList()).isEqualTo(LOCALE_LIST);
     }
 
+    @Test
+    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void
+    restoreValue_metricsFlagIsEnabled_restoresSetting_secureUri_logsSuccessWithSecureDatatype()
+    {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Settings.Secure.CONTENT_URI,
+                SETTING_KEY,
+                SETTING_VALUE,
+                /* restoredFromSdkInt */ 0);
+
+        DataTypeResult loggingResult =
+            getLoggingResultForDatatype(SettingsBackupRestoreKeys.KEY_SECURE);
+        assertThat(loggingResult).isNotNull();
+        assertThat(loggingResult.getSuccessCount()).isEqualTo(1);
+    }
+
+    @Test
+    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void
+    restoreValue_metricsFlagIsEnabled_restoresSetting_systemUri_logsSuccessWithSystemDatatype()
+    {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Settings.System.CONTENT_URI,
+                SETTING_KEY,
+                SETTING_VALUE,
+                /* restoredFromSdkInt */ 0);
+
+        DataTypeResult loggingResult =
+            getLoggingResultForDatatype(SettingsBackupRestoreKeys.KEY_SYSTEM);
+        assertThat(loggingResult).isNotNull();
+        assertThat(loggingResult.getSuccessCount()).isEqualTo(1);
+    }
+
+    @Test
+    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void
+    restoreValue_metricsFlagIsEnabled_restoresSetting_globalUri_logsSuccessWithGlobalDatatype()
+    {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Settings.Global.CONTENT_URI,
+                SETTING_KEY,
+                SETTING_VALUE,
+                /* restoredFromSdkInt */ 0);
+
+        DataTypeResult loggingResult =
+            getLoggingResultForDatatype(SettingsBackupRestoreKeys.KEY_GLOBAL);
+        assertThat(loggingResult).isNotNull();
+        assertThat(loggingResult.getSuccessCount()).isEqualTo(1);
+    }
+
+    @Test
+    @EnableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void restoreValue_metricsFlagIsEnabled_doesNotRestoreSetting_logsFailure() {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Uri.EMPTY,
+                SETTING_KEY,
+                SETTING_VALUE,
+                /* restoredFromSdkInt */ 0);
+
+        DataTypeResult loggingResult =
+            getLoggingResultForDatatype(SettingsBackupRestoreKeys.KEY_UNKNOWN);
+        assertThat(loggingResult).isNotNull();
+        assertThat(loggingResult.getFailCount()).isEqualTo(1);
+    }
+
+    @Test
+    @DisableFlags(com.android.server.backup.Flags.FLAG_ENABLE_METRICS_SETTINGS_BACKUP_AGENTS)
+    public void restoreValue_metricsFlagIsDisabled_doesNotLogMetrics() {
+        mSettingsHelper.restoreValue(
+                mContext,
+                mContentResolver,
+                new ContentValues(),
+                Uri.EMPTY,
+                SETTING_KEY,
+                SETTING_VALUE,
+                /* restoredFromSdkInt */ 0);
+
+        assertThat(getLoggingResultForDatatype(SettingsBackupRestoreKeys.KEY_UNKNOWN)).isNull();
+    }
+
     private int getAutoRotationSettingValue() {
         return Settings.System.getInt(mContentResolver,
                 Settings.System.ACCELEROMETER_ROTATION,
@@ -851,4 +956,13 @@
         assertThat(Settings.System.getString(mContentResolver, settings))
                 .isEqualTo(testRingtoneSettingsValue);
     }
+
+    private DataTypeResult getLoggingResultForDatatype(String dataType) {
+        for (DataTypeResult result : mBackupRestoreEventLogger.getLoggingResults()) {
+            if (result.getDataType().equals(dataType)) {
+                return result;
+            }
+        }
+        return null;
+    }
 }
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
index 9cce431..119b287 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
@@ -16,7 +16,7 @@
 
 package com.android.providers.settings;
 
-import static android.provider.Settings.Secure.ACCESSIBILITY_ENABLED;
+import static android.provider.Settings.Secure.CONTENT_CAPTURE_ENABLED;
 import static android.provider.Settings.Secure.SYNC_PARENT_SOUNDS;
 import static android.provider.Settings.System.RINGTONE;
 
@@ -67,7 +67,7 @@
     private static final String SPACE_SYSTEM = "system";
     private static final String SPACE_SECURE = "secure";
 
-    private static final String CLONE_TO_MANAGED_PROFILE_SETTING = ACCESSIBILITY_ENABLED;
+    private static final String CLONE_TO_MANAGED_PROFILE_SETTING = CONTENT_CAPTURE_ENABLED;
     private static final String CLONE_FROM_PARENT_SETTINGS = RINGTONE;
     private static final String SYNC_FROM_PARENT_SETTINGS = SYNC_PARENT_SOUNDS;
 
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/UpgradeControllerTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/UpgradeControllerTest.java
new file mode 100644
index 0000000..26ff376
--- /dev/null
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/UpgradeControllerTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.settings;
+
+import static android.provider.Settings.System.MIN_REFRESH_RATE;
+import static android.provider.Settings.System.PEAK_REFRESH_RATE;
+
+import static com.android.providers.settings.SettingsProvider.SETTINGS_TYPE_GLOBAL;
+import static com.android.providers.settings.SettingsProvider.SETTINGS_TYPE_SECURE;
+import static com.android.providers.settings.SettingsProvider.SETTINGS_TYPE_SYSTEM;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.IPackageManager;
+import android.os.Looper;
+import android.os.SystemConfigManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class UpgradeControllerTest {
+    private static final int USER_ID = UserHandle.USER_SYSTEM;
+    private static final float HIGHEST_REFRESH_RATE = 130f;
+
+    private final Context mContext =
+            spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
+    private final SettingsProvider.SettingsRegistry.UpgradeController.Injector mInjector =
+            new SettingsProvider.SettingsRegistry.UpgradeController.Injector() {
+                @Override
+                float findHighestRefreshRateForDefaultDisplay(Context context) {
+                    return HIGHEST_REFRESH_RATE;
+                }
+            };
+    private final SettingsProvider mSettingsProvider = new SettingsProvider() {
+        @Override
+        public boolean onCreate() {
+            return true;
+        }
+    };
+    private final SettingsProvider.SettingsRegistry mSettingsRegistry =
+            mSettingsProvider.new SettingsRegistry(Looper.getMainLooper());
+    private final SettingsProvider.SettingsRegistry.UpgradeController mUpgradeController =
+            mSettingsRegistry.new UpgradeController(mInjector, USER_ID);
+
+    @Mock
+    private UserManager mUserManager;
+
+    @Mock
+    private IPackageManager mPackageManager;
+
+    @Mock
+    private SystemConfigManager mSysConfigManager;
+
+    @Mock
+    private SettingsState mSystemSettings;
+
+    @Mock
+    private SettingsState mSecureSettings;
+
+    @Mock
+    private SettingsState mGlobalSettings;
+
+    @Mock
+    private SettingsState.Setting mMockSetting;
+
+    @Mock
+    private SettingsState.Setting mPeakRefreshRateSetting;
+
+    @Mock
+    private SettingsState.Setting mMinRefreshRateSetting;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mSettingsProvider.attachInfoForTesting(mContext, /* info= */ null);
+        mSettingsProvider.injectServices(mUserManager, mPackageManager, mSysConfigManager);
+        when(mSystemSettings.getSettingLocked(any())).thenReturn(mMockSetting);
+        when(mSecureSettings.getSettingLocked(any())).thenReturn(mMockSetting);
+        when(mGlobalSettings.getSettingLocked(any())).thenReturn(mMockSetting);
+        when(mMockSetting.isNull()).thenReturn(true);
+        when(mMockSetting.getValue()).thenReturn("0");
+
+        when(mSystemSettings.getSettingLocked(PEAK_REFRESH_RATE))
+                .thenReturn(mPeakRefreshRateSetting);
+        when(mSystemSettings.getSettingLocked(MIN_REFRESH_RATE))
+                .thenReturn(mMinRefreshRateSetting);
+
+        mSettingsRegistry.injectSettings(mSystemSettings, SETTINGS_TYPE_SYSTEM, USER_ID);
+        mSettingsRegistry.injectSettings(mSecureSettings, SETTINGS_TYPE_SECURE, USER_ID);
+        mSettingsRegistry.injectSettings(mGlobalSettings, SETTINGS_TYPE_GLOBAL, USER_ID);
+
+        // Lowest version so that all upgrades are run
+        when(mSecureSettings.getVersionLocked()).thenReturn(118);
+    }
+
+    @Test
+    public void testUpgrade_refreshRateSettings_defaultValues() {
+        when(mPeakRefreshRateSetting.isNull()).thenReturn(true);
+        when(mMinRefreshRateSetting.isNull()).thenReturn(true);
+
+        mUpgradeController.upgradeIfNeededLocked();
+
+        // Should remain unchanged
+        verify(mSystemSettings, never()).insertSettingLocked(eq(PEAK_REFRESH_RATE),
+                /* value= */ any(), /* tag= */ any(), /* makeDefault= */ anyBoolean(),
+                /* packageName= */ any());
+        verify(mSystemSettings, never()).insertSettingLocked(eq(MIN_REFRESH_RATE),
+                /* value= */ any(), /* tag= */ any(), /* makeDefault= */ anyBoolean(),
+                /* packageName= */ any());
+    }
+
+    @Test
+    public void testUpgrade_refreshRateSettings_enabled() {
+        when(mPeakRefreshRateSetting.isNull()).thenReturn(false);
+        when(mMinRefreshRateSetting.isNull()).thenReturn(false);
+        when(mPeakRefreshRateSetting.getValue()).thenReturn(String.valueOf(HIGHEST_REFRESH_RATE));
+        when(mMinRefreshRateSetting.getValue()).thenReturn(String.valueOf(HIGHEST_REFRESH_RATE));
+
+        mUpgradeController.upgradeIfNeededLocked();
+
+        // Highest refresh rate gets converted to infinity
+        verify(mSystemSettings).insertSettingLocked(eq(PEAK_REFRESH_RATE),
+                eq(String.valueOf(Float.POSITIVE_INFINITY)), /* tag= */ any(),
+                /* makeDefault= */ anyBoolean(), /* packageName= */ any());
+        verify(mSystemSettings).insertSettingLocked(eq(MIN_REFRESH_RATE),
+                eq(String.valueOf(Float.POSITIVE_INFINITY)), /* tag= */ any(),
+                /* makeDefault= */ anyBoolean(), /* packageName= */ any());
+    }
+
+    @Test
+    public void testUpgrade_refreshRateSettings_disabled() {
+        when(mPeakRefreshRateSetting.isNull()).thenReturn(false);
+        when(mMinRefreshRateSetting.isNull()).thenReturn(false);
+        when(mPeakRefreshRateSetting.getValue()).thenReturn("70f");
+        when(mMinRefreshRateSetting.getValue()).thenReturn("70f");
+
+        mUpgradeController.upgradeIfNeededLocked();
+
+        // Should remain unchanged
+        verify(mSystemSettings, never()).insertSettingLocked(eq(PEAK_REFRESH_RATE),
+                /* value= */ any(), /* tag= */ any(), /* makeDefault= */ anyBoolean(),
+                /* packageName= */ any());
+        verify(mSystemSettings, never()).insertSettingLocked(eq(MIN_REFRESH_RATE),
+                /* value= */ any(), /* tag= */ any(), /* makeDefault= */ anyBoolean(),
+                /* packageName= */ any());
+    }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index fb4293a..46bd88f 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -994,6 +994,9 @@
     <uses-permission android:name="android.permission.ACCESS_TEXT_CLASSIFIER_BY_TYPE"
         android:featureFlag="android.permission.flags.text_classifier_choice_api_enabled"/>
 
+    <!-- Permission required for CTS test - CtsContentProviderMultiUserTest -->
+    <uses-permission android:name="android.permission.RESOLVE_COMPONENT_FOR_UID" />
+
     <application
         android:label="@string/app_label"
         android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 3d250fd..3ee2db1 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -85,6 +85,7 @@
 filegroup {
     name: "SystemUI-tests-broken-robofiles-run",
     srcs: [
+        "tests/src/**/systemui/dreams/touch/CommunalTouchHandlerTest.java",
         "tests/src/**/systemui/shade/NotificationShadeWindowViewControllerTest.kt",
         "tests/src/**/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt",
         "tests/src/**/systemui/statusbar/pipeline/mobile/ui/model/SignalIconModelParameterizedTest.kt",
@@ -269,7 +270,7 @@
         "tests/src/**/systemui/stylus/StylusManagerTest.kt",
         "tests/src/**/systemui/recents/OverviewProxyServiceTest.kt",
         "tests/src/**/systemui/DisplayCutoutBaseViewTest.kt",
-        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt",
+        "tests/src/**/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImplTest.kt",
         "tests/src/**/systemui/statusbar/policy/BatteryControllerTest.java",
         "tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerTest.kt",
         "tests/src/**/systemui/statusbar/KeyboardShortcutsReceiverTest.java",
@@ -418,6 +419,9 @@
         "androidx.slice_slice-view",
     ],
     manifest: "AndroidManifest-res.xml",
+    flags_packages: [
+        "com_android_systemui_flags",
+    ],
 }
 
 android_library {
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 3b408e6..87fb58e 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -547,14 +547,6 @@
 }
 
 flag {
-   name: "migrate_clocks_to_blueprint"
-   namespace: "systemui"
-   description: "Move clock related views from KeyguardStatusView to KeyguardRootView, "
-        "and use modern architecture for lockscreen clocks"
-   bug: "301502635"
-}
-
-flag {
    name: "clock_reactive_variants"
    namespace: "systemui"
    description: "Add reactive variant fonts to some clocks"
@@ -1222,6 +1214,13 @@
 }
 
 flag {
+  name: "low_light_clock_dream"
+  namespace: "systemui"
+  description: "Enables low light clock dream experience on mobile phones"
+  bug: "378174125"
+}
+
+flag {
   name: "communal_standalone_support"
   namespace: "systemui"
   description: "Support communal features without a dock"
@@ -1236,6 +1235,21 @@
 }
 
 flag {
+  name: "glanceable_hub_v2_resources"
+  namespace: "systemui"
+  description: "Read only flag for rolling out glanceable hub v2 resource values"
+  bug: "375689917"
+  is_fixed_read_only: true
+}
+
+flag {
+    name: "glanceable_hub_back_action"
+    namespace: "systemui"
+    description: "Support back action from glanceable hub"
+    bug: "382771533"
+}
+
+flag {
     name: "dream_overlay_updated_font"
     namespace: "systemui"
     description: "Flag to enable updated font settings for dream overlay"
@@ -1789,6 +1803,15 @@
   bug: "371224114"
 }
 
+flag {
+  name: "disable_shade_expands_on_trackpad_two_finger_swipe"
+  namespace: "systemui"
+  description: "Disables expansion of the shade via two finger swipe on a trackpad"
+  bug: "356804470"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
 
 flag {
     name: "keyboard_shortcut_helper_shortcut_customizer"
@@ -1889,3 +1912,10 @@
    description: "Invokes edit mode directly from long press in glanceable hub"
    bug: "382531177"
 }
+
+flag {
+   name: "notification_magic_actions_treatment"
+   namespace: "systemui"
+   description: "Special UI treatment for magic actions"
+   bug: "383567383"
+}
diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
index ca2b957..7d27a56 100644
--- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
+++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
@@ -195,7 +195,10 @@
         // Create the origin leash and add to the transition root leash.
         mOriginLeash =
                 new SurfaceControl.Builder().setName("OriginTransition-origin-leash").build();
-        mStartTransaction
+
+        // Create temporary transaction to build
+        final SurfaceControl.Transaction tmpTransaction = new SurfaceControl.Transaction();
+        tmpTransaction
                 .reparent(mOriginLeash, rootLeash)
                 .show(mOriginLeash)
                 .setCornerRadius(mOriginLeash, windowRadius)
@@ -208,14 +211,14 @@
             int mode = change.getMode();
             SurfaceControl leash = change.getLeash();
             // Reparent leash to the transition root.
-            mStartTransaction.reparent(leash, rootLeash);
+            tmpTransaction.reparent(leash, rootLeash);
             if (TransitionUtil.isOpeningMode(mode)) {
                 openingSurfaces.add(change.getLeash());
                 // For opening surfaces, ending bounds are base bound. Apply corner radius if
                 // it's full screen.
                 Rect bounds = change.getEndAbsBounds();
                 if (displayBounds.equals(bounds)) {
-                    mStartTransaction
+                    tmpTransaction
                             .setCornerRadius(leash, windowRadius)
                             .setWindowCrop(leash, bounds.width(), bounds.height());
                 }
@@ -226,28 +229,53 @@
                 // it's full screen.
                 Rect bounds = change.getStartAbsBounds();
                 if (displayBounds.equals(bounds)) {
-                    mStartTransaction
+                    tmpTransaction
                             .setCornerRadius(leash, windowRadius)
                             .setWindowCrop(leash, bounds.width(), bounds.height());
                 }
             }
         }
 
+        if (openingSurfaces.isEmpty() && closingSurfaces.isEmpty()) {
+            logD("prepareUIs: no opening/closing surfaces available, nothing to prepare.");
+            return false;
+        }
+
         // Set relative order:
         // ----  App1  ----
         // ---- origin ----
         // ----  App2  ----
+
         if (mIsEntry) {
-            mStartTransaction
-                    .setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1)
-                    .setRelativeLayer(
-                            openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1);
+            if (!closingSurfaces.isEmpty()) {
+                tmpTransaction
+                        .setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1);
+            } else {
+                logW("Missing closing surface is entry transition");
+            }
+            if (!openingSurfaces.isEmpty()) {
+                tmpTransaction
+                        .setRelativeLayer(
+                                openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1);
+            } else {
+                logW("Missing opening surface is entry transition");
+            }
+
         } else {
-            mStartTransaction
-                    .setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1)
-                    .setRelativeLayer(
-                            closingSurfaces.get(closingSurfaces.size() - 1), mOriginLeash, 1);
+            if (!openingSurfaces.isEmpty()) {
+                tmpTransaction
+                        .setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1);
+            } else {
+                logW("Missing opening surface is exit transition");
+            }
+            if (!closingSurfaces.isEmpty()) {
+                tmpTransaction.setRelativeLayer(
+                        closingSurfaces.get(closingSurfaces.size() - 1), mOriginLeash, 1);
+            } else {
+                logW("Missing closing surface is exit transition");
+            }
         }
+        mStartTransaction.merge(tmpTransaction);
 
         // Attach origin UIComponent to origin leash.
         mOriginTransaction = mOrigin.newTransaction();
@@ -300,6 +328,7 @@
     }
 
     private void cancel() {
+        logD("cancel()");
         if (mAnimator != null) {
             mAnimator.cancel();
         }
@@ -311,6 +340,10 @@
         }
     }
 
+    private static void logW(String msg) {
+        Log.w(TAG, msg);
+    }
+
     private static void logE(String msg) {
         Log.e(TAG, msg);
     }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
index 41a00f5..b0c7ac0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.animation
 
 import android.app.ActivityManager
-import android.app.ActivityOptions
 import android.app.ActivityTaskManager
 import android.app.PendingIntent
 import android.app.TaskInfo
@@ -292,7 +291,7 @@
                 ?: throw IllegalStateException(
                     "ActivityTransitionAnimator.callback must be set before using this animator"
                 )
-        val runner = createRunner(controller)
+        val runner = createEphemeralRunner(controller)
         val runnerDelegate = runner.delegate
         val hideKeyguardWithAnimation = callback.isOnKeyguard() && !showOverLockscreen
 
@@ -416,7 +415,7 @@
 
         var cleanUpRunnable: Runnable? = null
         val returnRunner =
-            createRunner(
+            createEphemeralRunner(
                 object : DelegateTransitionAnimatorController(launchController) {
                     override val isLaunching = false
 
@@ -458,11 +457,7 @@
                 "${launchController.transitionCookie}_returnTransition",
             )
 
-        transitionRegister?.register(
-            filter,
-            transition,
-            includeTakeover = longLivedReturnAnimationsEnabled(),
-        )
+        transitionRegister?.register(filter, transition, includeTakeover = false)
         cleanUpRunnable = Runnable { transitionRegister?.unregister(transition) }
     }
 
@@ -476,12 +471,14 @@
         listeners.remove(listener)
     }
 
-    /** Create a new animation [Runner] controlled by [controller]. */
+    /**
+     * Create a new animation [Runner] controlled by [controller].
+     *
+     * This method must only be used for ephemeral (launch or return) transitions. Otherwise, use
+     * [createLongLivedRunner].
+     */
     @VisibleForTesting
-    @JvmOverloads
-    fun createRunner(controller: Controller, longLived: Boolean = false): Runner {
-        if (longLived) assertLongLivedReturnAnimations()
-
+    fun createEphemeralRunner(controller: Controller): Runner {
         // Make sure we use the modified timings when animating a dialog into an app.
         val transitionAnimator =
             if (controller.isDialogLaunch) {
@@ -490,7 +487,22 @@
                 transitionAnimator
             }
 
-        return Runner(controller, callback!!, transitionAnimator, lifecycleListener, longLived)
+        return Runner(controller, callback!!, transitionAnimator, lifecycleListener)
+    }
+
+    /**
+     * Create a new animation [Runner] controlled by the [Controller] that [controllerFactory] can
+     * create based on [forLaunch].
+     *
+     * This method must only be used for long-lived registrations. Otherwise, use
+     * [createEphemeralRunner].
+     */
+    @VisibleForTesting
+    fun createLongLivedRunner(controllerFactory: ControllerFactory, forLaunch: Boolean): Runner {
+        assertLongLivedReturnAnimations()
+        return Runner(callback!!, transitionAnimator, lifecycleListener) {
+            controllerFactory.createController(forLaunch)
+        }
     }
 
     interface PendingIntentStarter {
@@ -537,6 +549,23 @@
     }
 
     /**
+     * A factory used to create instances of [Controller] linked to a specific cookie [cookie] and
+     * [component].
+     */
+    abstract class ControllerFactory(
+        val cookie: TransitionCookie,
+        val component: ComponentName?,
+        val launchCujType: Int? = null,
+        val returnCujType: Int? = null,
+    ) {
+        /**
+         * Creates a [Controller] for launching or returning from the activity linked to [cookie]
+         * and [component].
+         */
+        abstract fun createController(forLaunch: Boolean): Controller
+    }
+
+    /**
      * A controller that takes care of applying the animation to an expanding view.
      *
      * Note that all callbacks (onXXX methods) are all called on the main thread.
@@ -656,13 +685,13 @@
     }
 
     /**
-     * Registers [controller] as a long-lived transition handler for launch and return animations.
+     * Registers [controllerFactory] as a long-lived transition handler for launch and return
+     * animations.
      *
-     * The [controller] will only be used for transitions matching the [TransitionCookie] defined
-     * within it, or the [ComponentName] if the cookie matching fails. Both fields are mandatory for
-     * this registration.
+     * The [Controller]s created by [controllerFactory] will only be used for transitions matching
+     * the [cookie], or the [ComponentName] defined within it if the cookie matching fails.
      */
-    fun register(controller: Controller) {
+    fun register(cookie: TransitionCookie, controllerFactory: ControllerFactory) {
         assertLongLivedReturnAnimations()
 
         if (transitionRegister == null) {
@@ -672,13 +701,8 @@
             )
         }
 
-        val cookie =
-            controller.transitionCookie
-                ?: throw IllegalStateException(
-                    "A cookie must be defined in order to use long-lived animations"
-                )
         val component =
-            controller.component
+            controllerFactory.component
                 ?: throw IllegalStateException(
                     "A component must be defined in order to use long-lived animations"
                 )
@@ -699,15 +723,11 @@
             }
         val launchRemoteTransition =
             RemoteTransition(
-                OriginTransition(createRunner(controller, longLived = true)),
+                OriginTransition(createLongLivedRunner(controllerFactory, forLaunch = true)),
                 "${cookie}_launchTransition",
             )
         transitionRegister.register(launchFilter, launchRemoteTransition, includeTakeover = true)
 
-        val returnController =
-            object : Controller by controller {
-                override val isLaunching: Boolean = false
-            }
         // Cross-task close transitions should not use this animation, so we only register it for
         // when the opening window is Launcher.
         val returnFilter =
@@ -727,7 +747,7 @@
             }
         val returnRemoteTransition =
             RemoteTransition(
-                OriginTransition(createRunner(returnController, longLived = true)),
+                OriginTransition(createLongLivedRunner(controllerFactory, forLaunch = false)),
                 "${cookie}_returnTransition",
             )
         transitionRegister.register(returnFilter, returnRemoteTransition, includeTakeover = true)
@@ -918,32 +938,61 @@
     }
 
     @VisibleForTesting
-    inner class Runner(
+    inner class Runner
+    private constructor(
         /**
          * This can hold a reference to a view, so it needs to be cleaned up and can't be held on to
-         * forever when ![longLived].
+         * forever. In case of a long-lived [Runner], this must be null and [controllerFactory] must
+         * be defined instead.
          */
         private var controller: Controller?,
+        /**
+         * Reusable factory to generate single-use controllers. In case of an ephemeral [Runner],
+         * this must be null and [controller] must be defined instead.
+         */
+        private val controllerFactory: (() -> Controller)?,
         private val callback: Callback,
         /** The animator to use to animate the window transition. */
         private val transitionAnimator: TransitionAnimator,
         /** Listener for animation lifecycle events. */
-        private val listener: Listener? = null,
-        /**
-         * Whether the internal should be kept around after execution for later usage. IMPORTANT:
-         * should always be false if this [Runner] is to be used directly with [ActivityOptions]
-         * (i.e. for ephemeral launches), or the controller will leak its view.
-         */
-        private val longLived: Boolean = false,
+        private val listener: Listener?,
     ) : IRemoteAnimationRunner.Stub() {
+        constructor(
+            controller: Controller,
+            callback: Callback,
+            transitionAnimator: TransitionAnimator,
+            listener: Listener? = null,
+        ) : this(
+            controller = controller,
+            controllerFactory = null,
+            callback = callback,
+            transitionAnimator = transitionAnimator,
+            listener = listener,
+        )
+
+        constructor(
+            callback: Callback,
+            transitionAnimator: TransitionAnimator,
+            listener: Listener? = null,
+            controllerFactory: () -> Controller,
+        ) : this(
+            controller = null,
+            controllerFactory = controllerFactory,
+            callback = callback,
+            transitionAnimator = transitionAnimator,
+            listener = listener,
+        )
+
         // This is being passed across IPC boundaries and cycles (through PendingIntentRecords,
         // etc.) are possible. So we need to make sure we drop any references that might
         // transitively cause leaks when we're done with animation.
         @VisibleForTesting var delegate: AnimationDelegate?
 
         init {
+            assert((controller != null).xor(controllerFactory != null))
+
             delegate = null
-            if (!longLived) {
+            if (controller != null) {
                 // Ephemeral launches bundle the runner with the launch request (instead of being
                 // registered ahead of time for later use). This means that there could be a timeout
                 // between creation and invocation, so the delegate needs to exist from the
@@ -1021,17 +1070,21 @@
 
         @AnyThread
         private fun maybeSetUp() {
-            if (!longLived || delegate != null) return
+            if (controllerFactory == null || delegate != null) return
             createDelegate()
         }
 
         @AnyThread
         private fun createDelegate() {
-            if (controller == null) return
+            var controller = controller
+            val factory = controllerFactory
+            if (controller == null && factory == null) return
+
+            controller = controller ?: factory!!.invoke()
             delegate =
                 AnimationDelegate(
                     mainExecutor,
-                    controller!!,
+                    controller,
                     callback,
                     DelegatingAnimationCompletionListener(listener, this::dispose),
                     transitionAnimator,
@@ -1041,13 +1094,12 @@
 
         @AnyThread
         fun dispose() {
-            // Drop references to animation controller once we're done with the animation
-            // to avoid leaking.
+            // Drop references to animation controller once we're done with the animation to avoid
+            // leaking in case of ephemeral launches. When long-lived, [controllerFactory] will
+            // still be around to create new controllers.
             mainExecutor.execute {
                 delegate = null
-                // When long lived, the same Runner can be used more than once. In this case we need
-                // to keep the controller around so we can rebuild the delegate on demand.
-                if (!longLived) controller = null
+                controller = null
             }
         }
     }
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
index 029b9cd..35e85a0 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedDraggable.kt
@@ -41,6 +41,7 @@
 import androidx.compose.ui.input.pointer.changedToDownIgnoreConsumed
 import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
 import androidx.compose.ui.input.pointer.positionChange
+import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.addPointerInputChange
 import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
@@ -55,8 +56,7 @@
 import androidx.compose.ui.util.fastSumBy
 import com.android.compose.modifiers.thenIf
 import kotlin.math.sign
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.async
 import kotlinx.coroutines.launch
 
 /**
@@ -67,6 +67,16 @@
  */
 interface NestedDraggable {
     /**
+     * Return whether we should start a drag given the pointer [change].
+     *
+     * This is called when the touch slop is reached. If this returns `true`, then the [change] will
+     * be consumed and [onDragStarted] will be called. If this returns `false`, then the current
+     * touch slop detection will be reset and restarted at the current
+     * [change position][PointerInputChange.position].
+     */
+    fun shouldStartDrag(change: PointerInputChange): Boolean = true
+
+    /**
      * Called when a drag is started in the given [position] (*before* dragging the touch slop) and
      * in the direction given by [sign], with the given number of [pointersDown] when the touch slop
      * was detected.
@@ -161,11 +171,7 @@
         }
 
     /** The controller created by the nested scroll logic (and *not* the drag logic). */
-    private var nestedScrollController: WrappedController? = null
-        set(value) {
-            field?.ensureOnDragStoppedIsCalled()
-            field = value
-        }
+    private var nestedScrollController: NestedScrollController? = null
 
     /**
      * The last pointer which was the first down since the last time all pointers were up.
@@ -183,6 +189,7 @@
 
     override fun onDetach() {
         nestedScrollController?.ensureOnDragStoppedIsCalled()
+        nestedScrollController = null
     }
 
     fun update(
@@ -199,6 +206,7 @@
         trackDownPositionDelegate?.resetPointerInputHandler()
         detectDragsDelegate?.resetPointerInputHandler()
         nestedScrollController?.ensureOnDragStoppedIsCalled()
+        nestedScrollController = null
 
         if (!enabled && trackDownPositionDelegate != null) {
             check(detectDragsDelegate != null)
@@ -248,8 +256,14 @@
 
             var overSlop = 0f
             val onTouchSlopReached = { change: PointerInputChange, over: Float ->
-                change.consume()
-                overSlop = over
+                if (draggable.shouldStartDrag(change)) {
+                    change.consume()
+                    overSlop = over
+                }
+
+                // If shouldStartDrag() returned false, then we didn't consume the event and
+                // awaitTouchSlopOrCancellation() will reset the touch slop detector so that the
+                // user has to drag by at least the touch slop again.
             }
 
             suspend fun AwaitPointerEventScope.awaitTouchSlopOrCancellation(
@@ -288,15 +302,21 @@
 
             if (drag != null) {
                 velocityTracker.resetTracking()
-                val sign = (drag.position - down.position).toFloat().sign
+                val sign = drag.positionChangeIgnoreConsumed().toFloat().sign
+                check(sign != 0f) {
+                    buildString {
+                        append("sign is equal to 0 ")
+                        append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
+                        append("down.position ${down.position} ")
+                        append("drag.position ${drag.position} ")
+                        append("drag.previousPosition ${drag.previousPosition}")
+                    }
+                }
+
                 check(pointersDownCount > 0) { "pointersDownCount is equal to $pointersDownCount" }
-                val wrappedController =
-                    WrappedController(
-                        coroutineScope,
-                        draggable.onDragStarted(down.position, sign, pointersDownCount),
-                    )
+                val controller = draggable.onDragStarted(down.position, sign, pointersDownCount)
                 if (overSlop != 0f) {
-                    onDrag(wrappedController, drag, overSlop, velocityTracker)
+                    onDrag(controller, drag, overSlop, velocityTracker)
                 }
 
                 // If a drag was started, we cancel any other drag started by a nested scrollable.
@@ -304,12 +324,13 @@
                 // Note: we cancel the nested drag here *after* starting the new drag so that in the
                 // STL case, the cancelled drag will not change the current scene of the STL.
                 nestedScrollController?.ensureOnDragStoppedIsCalled()
+                nestedScrollController = null
 
                 val isSuccessful =
                     try {
                         val onDrag = { change: PointerInputChange ->
                             onDrag(
-                                wrappedController,
+                                controller,
                                 change,
                                 change.positionChange().toFloat(),
                                 velocityTracker,
@@ -322,19 +343,17 @@
                             Orientation.Vertical -> verticalDrag(drag.id, onDrag)
                         }
                     } catch (t: Throwable) {
-                        wrappedController.ensureOnDragStoppedIsCalled()
+                        onDragStopped(controller, Velocity.Zero)
                         throw t
                     }
 
                 if (isSuccessful) {
                     val maxVelocity = currentValueOf(LocalViewConfiguration).maximumFlingVelocity
                     val velocity =
-                        velocityTracker
-                            .calculateVelocity(Velocity(maxVelocity, maxVelocity))
-                            .toFloat()
-                    onDragStopped(wrappedController, velocity)
+                        velocityTracker.calculateVelocity(Velocity(maxVelocity, maxVelocity))
+                    onDragStopped(controller, velocity)
                 } else {
-                    onDragStopped(wrappedController, velocity = 0f)
+                    onDragStopped(controller, Velocity.Zero)
                 }
             }
         }
@@ -348,88 +367,87 @@
     ) {
         velocityTracker.addPointerInputChange(change)
 
-        scrollWithOverscroll(delta) { deltaFromOverscroll ->
+        scrollWithOverscroll(delta.toOffset()) { deltaFromOverscroll ->
             scrollWithNestedScroll(deltaFromOverscroll) { deltaFromNestedScroll ->
-                controller.onDrag(deltaFromNestedScroll)
+                controller.onDrag(deltaFromNestedScroll.toFloat()).toOffset()
             }
         }
     }
 
-    private fun onDragStopped(controller: WrappedController, velocity: Float) {
-        coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
-            try {
-                flingWithOverscroll(velocity) { velocityFromOverscroll ->
-                    flingWithNestedScroll(velocityFromOverscroll) { velocityFromNestedScroll ->
-                        controller.onDragStopped(velocityFromNestedScroll)
-                    }
+    private fun onDragStopped(controller: NestedDraggable.Controller, velocity: Velocity) {
+        // We launch in the scope of the dispatcher so that the fling is not cancelled if this node
+        // is removed right after onDragStopped() is called.
+        nestedScrollDispatcher.coroutineScope.launch {
+            flingWithOverscroll(velocity) { velocityFromOverscroll ->
+                flingWithNestedScroll(velocityFromOverscroll) { velocityFromNestedScroll ->
+                    controller.onDragStopped(velocityFromNestedScroll.toFloat()).toVelocity()
                 }
-            } finally {
-                controller.ensureOnDragStoppedIsCalled()
             }
         }
     }
 
-    private fun scrollWithOverscroll(delta: Float, performScroll: (Float) -> Float): Float {
+    private fun scrollWithOverscroll(delta: Offset, performScroll: (Offset) -> Offset): Offset {
         val effect = overscrollEffect
         return if (effect != null) {
-            effect
-                .applyToScroll(delta.toOffset(), source = NestedScrollSource.UserInput) {
-                    performScroll(it.toFloat()).toOffset()
-                }
-                .toFloat()
+            effect.applyToScroll(delta, source = NestedScrollSource.UserInput) { performScroll(it) }
         } else {
             performScroll(delta)
         }
     }
 
-    private fun scrollWithNestedScroll(delta: Float, performScroll: (Float) -> Float): Float {
+    private fun scrollWithNestedScroll(delta: Offset, performScroll: (Offset) -> Offset): Offset {
         val preConsumed =
-            nestedScrollDispatcher
-                .dispatchPreScroll(
-                    available = delta.toOffset(),
-                    source = NestedScrollSource.UserInput,
-                )
-                .toFloat()
+            nestedScrollDispatcher.dispatchPreScroll(
+                available = delta,
+                source = NestedScrollSource.UserInput,
+            )
         val available = delta - preConsumed
         val consumed = performScroll(available)
         val left = available - consumed
         val postConsumed =
-            nestedScrollDispatcher
-                .dispatchPostScroll(
-                    consumed = (preConsumed + consumed).toOffset(),
-                    available = left.toOffset(),
-                    source = NestedScrollSource.UserInput,
-                )
-                .toFloat()
+            nestedScrollDispatcher.dispatchPostScroll(
+                consumed = preConsumed + consumed,
+                available = left,
+                source = NestedScrollSource.UserInput,
+            )
         return consumed + preConsumed + postConsumed
     }
 
     private suspend fun flingWithOverscroll(
-        velocity: Float,
-        performFling: suspend (Float) -> Float,
-    ) {
+        velocity: Velocity,
+        performFling: suspend (Velocity) -> Velocity,
+    ): Velocity {
         val effect = overscrollEffect
-        if (effect != null) {
-            effect.applyToFling(velocity.toVelocity()) { performFling(it.toFloat()).toVelocity() }
+        return flingWithOverscroll(effect, velocity, performFling)
+    }
+
+    private suspend fun flingWithOverscroll(
+        overscrollEffect: OverscrollEffect?,
+        velocity: Velocity,
+        performFling: suspend (Velocity) -> Velocity,
+    ): Velocity {
+        return if (overscrollEffect != null) {
+            overscrollEffect.applyToFling(velocity) { performFling(it) }
+
+            // Effects always consume the whole velocity.
+            velocity
         } else {
             performFling(velocity)
         }
     }
 
     private suspend fun flingWithNestedScroll(
-        velocity: Float,
-        performFling: suspend (Float) -> Float,
-    ): Float {
-        val preConsumed = nestedScrollDispatcher.dispatchPreFling(available = velocity.toVelocity())
-        val available = velocity - preConsumed.toFloat()
+        velocity: Velocity,
+        performFling: suspend (Velocity) -> Velocity,
+    ): Velocity {
+        val preConsumed = nestedScrollDispatcher.dispatchPreFling(available = velocity)
+        val available = velocity - preConsumed
         val consumed = performFling(available)
         val left = available - consumed
-        return nestedScrollDispatcher
-            .dispatchPostFling(
-                consumed = consumed.toVelocity() + preConsumed,
-                available = left.toVelocity(),
-            )
-            .toFloat()
+        return nestedScrollDispatcher.dispatchPostFling(
+            consumed = consumed + preConsumed,
+            available = left,
+        )
     }
 
     /*
@@ -459,8 +477,7 @@
 
     override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
         val controller = nestedScrollController ?: return Offset.Zero
-        val consumed = controller.onDrag(available.toFloat())
-        return consumed.toOffset()
+        return scrollWithOverscroll(controller, available)
     }
 
     override fun onPostScroll(
@@ -485,49 +502,43 @@
             // TODO(b/382665591): Replace this by check(pointersDownCount > 0).
             val pointersDown = pointersDownCount.coerceAtLeast(1)
             nestedScrollController =
-                WrappedController(
-                    coroutineScope,
+                NestedScrollController(
+                    overscrollEffect,
                     draggable.onDragStarted(startedPosition, sign, pointersDown),
                 )
         }
 
         val controller = nestedScrollController ?: return Offset.Zero
-        return controller.onDrag(offset).toOffset()
+        return scrollWithOverscroll(controller, available)
+    }
+
+    private fun scrollWithOverscroll(controller: NestedScrollController, offset: Offset): Offset {
+        return scrollWithOverscroll(offset) {
+            controller.controller.onDrag(it.toFloat()).toOffset()
+        }
     }
 
     override suspend fun onPreFling(available: Velocity): Velocity {
         val controller = nestedScrollController ?: return Velocity.Zero
         nestedScrollController = null
 
-        val consumed = controller.onDragStopped(available.toFloat())
-        return consumed.toVelocity()
-    }
-}
-
-/**
- * A controller that wraps [delegate] and can be used to ensure that [onDragStopped] is called, but
- * not more than once.
- */
-private class WrappedController(
-    private val coroutineScope: CoroutineScope,
-    private val delegate: NestedDraggable.Controller,
-) : NestedDraggable.Controller by delegate {
-    private var onDragStoppedCalled = false
-
-    override fun onDrag(delta: Float): Float {
-        if (onDragStoppedCalled) return 0f
-        return delegate.onDrag(delta)
+        return nestedScrollDispatcher.coroutineScope
+            .async { controller.flingWithOverscroll(available) }
+            .await()
     }
 
-    override suspend fun onDragStopped(velocity: Float): Float {
-        if (onDragStoppedCalled) return 0f
-        onDragStoppedCalled = true
-        return delegate.onDragStopped(velocity)
-    }
+    private inner class NestedScrollController(
+        private val overscrollEffect: OverscrollEffect?,
+        val controller: NestedDraggable.Controller,
+    ) {
+        fun ensureOnDragStoppedIsCalled() {
+            nestedScrollDispatcher.coroutineScope.launch { flingWithOverscroll(Velocity.Zero) }
+        }
 
-    fun ensureOnDragStoppedIsCalled() {
-        // Start with UNDISPATCHED so that onDragStopped() is always run until its first suspension
-        // point, even if coroutineScope is cancelled.
-        coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) { onDragStopped(velocity = 0f) }
+        suspend fun flingWithOverscroll(velocity: Velocity): Velocity {
+            return flingWithOverscroll(overscrollEffect, velocity) {
+                controller.onDragStopped(it.toFloat()).toVelocity()
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
index 735ab68..f98b090 100644
--- a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
+++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedDraggableTest.kt
@@ -32,6 +32,7 @@
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.input.pointer.PointerInputChange
 import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.test.junit4.ComposeContentTestRule
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -42,7 +43,8 @@
 import androidx.compose.ui.unit.Velocity
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.ceil
-import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.delay
 import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
@@ -62,9 +64,10 @@
     @Test
     fun simpleDrag() {
         val draggable = TestDraggable()
+        val effect = TestOverscrollEffect(orientation) { 0f }
         val touchSlop =
             rule.setContentWithTouchSlop {
-                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation, effect))
             }
 
         assertThat(draggable.onDragStartedCalled).isFalse()
@@ -89,6 +92,7 @@
 
         assertThat(draggable.onDragDelta).isEqualTo(30f)
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         rule.onRoot().performTouchInput {
             moveBy((-15f).toOffset())
@@ -97,16 +101,18 @@
 
         assertThat(draggable.onDragDelta).isEqualTo(15f)
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun nestedScrollable() {
         val draggable = TestDraggable()
+        val effect = TestOverscrollEffect(orientation) { 0f }
         val touchSlop =
             rule.setContentWithTouchSlop {
                 Box(
                     Modifier.fillMaxSize()
-                        .nestedDraggable(draggable, orientation)
+                        .nestedDraggable(draggable, orientation, effect)
                         .nestedScrollable(rememberScrollState())
                 )
             }
@@ -135,6 +141,7 @@
         assertThat(draggable.onDragCalled).isTrue()
         assertThat(draggable.onDragDelta).isEqualTo(-30f)
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         rule.onRoot().performTouchInput {
             moveBy(15f.toOffset())
@@ -145,15 +152,17 @@
         assertThat(draggable.onDragCalled).isTrue()
         assertThat(draggable.onDragDelta).isEqualTo(-15f)
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun onDragStoppedIsCalledWhenDraggableIsUpdatedAndReset() {
         val draggable = TestDraggable()
+        val effect = TestOverscrollEffect(orientation) { 0f }
         var orientation by mutableStateOf(orientation)
         val touchSlop =
             rule.setContentWithTouchSlop {
-                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation, effect))
             }
 
         assertThat(draggable.onDragStartedCalled).isFalse()
@@ -165,6 +174,7 @@
 
         assertThat(draggable.onDragStartedCalled).isTrue()
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         orientation =
             when (orientation) {
@@ -173,17 +183,19 @@
             }
         rule.waitForIdle()
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun onDragStoppedIsCalledWhenDraggableIsUpdatedAndReset_nestedScroll() {
         val draggable = TestDraggable()
+        val effect = TestOverscrollEffect(orientation) { 0f }
         var orientation by mutableStateOf(orientation)
         val touchSlop =
             rule.setContentWithTouchSlop {
                 Box(
                     Modifier.fillMaxSize()
-                        .nestedDraggable(draggable, orientation)
+                        .nestedDraggable(draggable, orientation, effect)
                         .nestedScrollable(rememberScrollState())
                 )
             }
@@ -197,6 +209,7 @@
 
         assertThat(draggable.onDragStartedCalled).isTrue()
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         orientation =
             when (orientation) {
@@ -205,16 +218,34 @@
             }
         rule.waitForIdle()
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun onDragStoppedIsCalledWhenDraggableIsRemovedDuringDrag() {
         val draggable = TestDraggable()
+        val postFlingDelay = 10 * 16L
+        val effect =
+            TestOverscrollEffect(
+                orientation,
+                onPostFling = {
+                    // We delay the fling so that we can check that the draggable node methods are
+                    // still called until completion even when the node is removed.
+                    delay(postFlingDelay)
+                    it
+                },
+            ) {
+                0f
+            }
         var composeContent by mutableStateOf(true)
         val touchSlop =
             rule.setContentWithTouchSlop {
-                if (composeContent) {
-                    Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+                // We add an empty nested scroll connection here from which the scope will be used
+                // when dispatching the flings.
+                Box(Modifier.nestedScroll(remember { object : NestedScrollConnection {} })) {
+                    if (composeContent) {
+                        Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation, effect))
+                    }
                 }
             }
 
@@ -227,24 +258,44 @@
 
         assertThat(draggable.onDragStartedCalled).isTrue()
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         composeContent = false
         rule.waitForIdle()
+        rule.mainClock.advanceTimeBy(postFlingDelay)
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun onDragStoppedIsCalledWhenDraggableIsRemovedDuringDrag_nestedScroll() {
         val draggable = TestDraggable()
+        val postFlingDelay = 10 * 16L
+        val effect =
+            TestOverscrollEffect(
+                orientation,
+                onPostFling = {
+                    // We delay the fling so that we can check that the draggable node methods are
+                    // still called until completion even when the node is removed.
+                    delay(postFlingDelay)
+                    it
+                },
+            ) {
+                0f
+            }
         var composeContent by mutableStateOf(true)
         val touchSlop =
             rule.setContentWithTouchSlop {
-                if (composeContent) {
-                    Box(
-                        Modifier.fillMaxSize()
-                            .nestedDraggable(draggable, orientation)
-                            .nestedScrollable(rememberScrollState())
-                    )
+                // We add an empty nested scroll connection here from which the scope will be used
+                // when dispatching the flings.
+                Box(Modifier.nestedScroll(remember { object : NestedScrollConnection {} })) {
+                    if (composeContent) {
+                        Box(
+                            Modifier.fillMaxSize()
+                                .nestedDraggable(draggable, orientation, effect)
+                                .nestedScrollable(rememberScrollState())
+                        )
+                    }
                 }
             }
 
@@ -257,17 +308,22 @@
 
         assertThat(draggable.onDragStartedCalled).isTrue()
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
 
         composeContent = false
         rule.waitForIdle()
+        rule.mainClock.advanceTimeBy(postFlingDelay)
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
     fun onDragStoppedIsCalledWhenDraggableIsRemovedDuringFling() {
         val draggable = TestDraggable()
+        val effect = TestOverscrollEffect(orientation) { 0f }
         var composeContent by mutableStateOf(true)
         var preFlingCalled = false
+        val unblockPrefling = CompletableDeferred<Velocity>()
         rule.setContent {
             if (composeContent) {
                 Box(
@@ -281,12 +337,12 @@
                                 object : NestedScrollConnection {
                                     override suspend fun onPreFling(available: Velocity): Velocity {
                                         preFlingCalled = true
-                                        awaitCancellation()
+                                        return unblockPrefling.await()
                                     }
                                 }
                             }
                         )
-                        .nestedDraggable(draggable, orientation)
+                        .nestedDraggable(draggable, orientation, effect)
                 )
             }
         }
@@ -303,11 +359,14 @@
 
         assertThat(draggable.onDragStartedCalled).isTrue()
         assertThat(draggable.onDragStoppedCalled).isFalse()
+        assertThat(effect.applyToFlingDone).isFalse()
         assertThat(preFlingCalled).isTrue()
 
         composeContent = false
+        unblockPrefling.complete(Velocity.Zero)
         rule.waitForIdle()
         assertThat(draggable.onDragStoppedCalled).isTrue()
+        assertThat(effect.applyToFlingDone).isTrue()
     }
 
     @Test
@@ -457,6 +516,83 @@
         assertThat(draggable.onDragStartedPointersDown).isEqualTo(6)
     }
 
+    @Test
+    fun shouldStartDrag() {
+        val draggable = TestDraggable()
+        val touchSlop =
+            rule.setContentWithTouchSlop {
+                Box(Modifier.fillMaxSize().nestedDraggable(draggable, orientation))
+            }
+
+        // Drag in one direction.
+        draggable.shouldStartDrag = false
+        rule.onRoot().performTouchInput {
+            down(center)
+            moveBy(touchSlop.toOffset())
+        }
+        assertThat(draggable.onDragStartedCalled).isFalse()
+
+        // Drag in the other direction.
+        draggable.shouldStartDrag = true
+        rule.onRoot().performTouchInput { moveBy(-touchSlop.toOffset()) }
+        assertThat(draggable.onDragStartedCalled).isTrue()
+        assertThat(draggable.onDragStartedSign).isEqualTo(-1f)
+        assertThat(draggable.onDragDelta).isEqualTo(0f)
+    }
+
+    @Test
+    fun overscrollEffectIsUsedDuringNestedScroll() {
+        var consumeDrag = true
+        var consumedByDrag = 0f
+        var consumedByEffect = 0f
+        val draggable =
+            TestDraggable(
+                onDrag = {
+                    if (consumeDrag) {
+                        consumedByDrag += it
+                        it
+                    } else {
+                        0f
+                    }
+                }
+            )
+        val effect =
+            TestOverscrollEffect(orientation) { delta ->
+                /* Consumes everything. */
+                consumedByEffect += delta
+                delta
+            }
+
+        val touchSlop =
+            rule.setContentWithTouchSlop {
+                Box(
+                    Modifier.fillMaxSize()
+                        .nestedDraggable(draggable, orientation, overscrollEffect = effect)
+                        .nestedScrollable(rememberScrollState())
+                )
+            }
+
+        // Swipe on the nested scroll. The draggable consumes the scrolls.
+        rule.onRoot().performTouchInput {
+            down(center)
+            moveBy((touchSlop + 10f).toOffset())
+        }
+        assertThat(draggable.onDragStartedCalled).isTrue()
+        assertThat(consumedByDrag).isEqualTo(10f)
+        assertThat(consumedByEffect).isEqualTo(0f)
+
+        // Stop consuming the scrolls in the draggable. The overscroll effect should now consume
+        // the scrolls.
+        consumeDrag = false
+        rule.onRoot().performTouchInput { moveBy(20f.toOffset()) }
+        assertThat(consumedByDrag).isEqualTo(10f)
+        assertThat(consumedByEffect).isEqualTo(20f)
+
+        assertThat(effect.applyToFlingDone).isFalse()
+        rule.onRoot().performTouchInput { up() }
+        assertThat(effect.applyToFlingDone).isTrue()
+    }
+
     private fun ComposeContentTestRule.setContentWithTouchSlop(
         content: @Composable () -> Unit
     ): Float {
@@ -481,6 +617,7 @@
         private val onDragStopped: suspend (Float) -> Float = { it },
         private val shouldConsumeNestedScroll: (Float) -> Boolean = { true },
     ) : NestedDraggable {
+        var shouldStartDrag = true
         var onDragStartedCalled = false
         var onDragCalled = false
         var onDragStoppedCalled = false
@@ -490,6 +627,8 @@
         var onDragStartedPointersDown = 0
         var onDragDelta = 0f
 
+        override fun shouldStartDrag(change: PointerInputChange): Boolean = shouldStartDrag
+
         override fun onDragStarted(
             position: Offset,
             sign: Float,
diff --git a/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/TestOverscrollEffect.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/TestOverscrollEffect.kt
new file mode 100644
index 0000000..8bf9c21
--- /dev/null
+++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/TestOverscrollEffect.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.gesture
+
+import androidx.compose.foundation.OverscrollEffect
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.nestedscroll.NestedScrollSource
+import androidx.compose.ui.unit.Velocity
+
+class TestOverscrollEffect(
+    override val orientation: Orientation,
+    private val onPostFling: suspend (Float) -> Float = { it },
+    private val onPostScroll: (Float) -> Float,
+) : OverscrollEffect, OrientationAware {
+    override val isInProgress: Boolean = false
+    var applyToFlingDone = false
+        private set
+
+    override fun applyToScroll(
+        delta: Offset,
+        source: NestedScrollSource,
+        performScroll: (Offset) -> Offset,
+    ): Offset {
+        val consumedByScroll = performScroll(delta)
+        val available = delta - consumedByScroll
+        val consumedByEffect = onPostScroll(available.toFloat()).toOffset()
+        return consumedByScroll + consumedByEffect
+    }
+
+    override suspend fun applyToFling(
+        velocity: Velocity,
+        performFling: suspend (Velocity) -> Velocity,
+    ) {
+        val consumedByFling = performFling(velocity)
+        val available = velocity - consumedByFling
+        onPostFling(available.toFloat())
+        applyToFlingDone = true
+    }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index beaf963..9ab2812 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -8,7 +8,6 @@
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.background
 import androidx.compose.foundation.focusable
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
@@ -128,9 +127,6 @@
             fade(Communal.Elements.Grid)
         }
     }
-    // Disable horizontal overscroll. If the scene is overscrolled too soon after showing, this
-    // can lead to inconsistent KeyguardState changes.
-    overscrollDisabled(CommunalScenes.Communal, Orientation.Horizontal)
 }
 
 /**
@@ -205,7 +201,6 @@
                 colors = colors,
                 content = content,
                 viewModel = viewModel,
-                modifier = Modifier.horizontalNestedScrollToScene(),
             )
         }
     }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
index a17a1d4..0a0003e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
@@ -19,17 +19,20 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntRect
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
 import com.android.compose.animation.scene.SceneScope
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
 import com.android.systemui.communal.smartspace.SmartspaceInteractionHandler
 import com.android.systemui.communal.ui.compose.section.AmbientStatusBarSection
 import com.android.systemui.communal.ui.compose.section.CommunalPopupSection
@@ -39,8 +42,11 @@
 import com.android.systemui.keyguard.ui.composable.blueprint.BlueprintAlignmentLines
 import com.android.systemui.keyguard.ui.composable.section.BottomAreaSection
 import com.android.systemui.keyguard.ui.composable.section.LockSection
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
 import javax.inject.Inject
+import kotlin.math.min
+import kotlin.math.roundToInt
 
 /** Renders the content of the glanceable hub. */
 class CommunalContent
@@ -48,6 +54,7 @@
 constructor(
     private val viewModel: CommunalViewModel,
     private val interactionHandler: SmartspaceInteractionHandler,
+    private val communalSettingsInteractor: CommunalSettingsInteractor,
     private val dialogFactory: SystemUIDialogFactory,
     private val lockSection: LockSection,
     private val bottomAreaSection: BottomAreaSection,
@@ -77,11 +84,20 @@
                             sceneScope = this@Content,
                         )
                     }
-                    with(lockSection) {
-                        LockIcon(
-                            overrideColor = MaterialTheme.colorScheme.onPrimaryContainer,
+                    if (communalSettingsInteractor.isV2FlagEnabled()) {
+                        Icon(
+                            painter = painterResource(id = R.drawable.ic_lock),
+                            contentDescription = null,
+                            tint = MaterialTheme.colorScheme.onPrimaryContainer,
                             modifier = Modifier.element(Communal.Elements.LockIcon),
                         )
+                    } else {
+                        with(lockSection) {
+                            LockIcon(
+                                overrideColor = MaterialTheme.colorScheme.onPrimaryContainer,
+                                modifier = Modifier.element(Communal.Elements.LockIcon),
+                            )
+                        }
                     }
                     with(bottomAreaSection) {
                         IndicationArea(
@@ -98,14 +114,42 @@
 
                 val noMinConstraints = constraints.copy(minWidth = 0, minHeight = 0)
 
-                val lockIconPlaceable = lockIconMeasurable.measure(noMinConstraints)
+                val lockIconPlaceable =
+                    if (communalSettingsInteractor.isV2FlagEnabled()) {
+                        val lockIconSizeInt = lockIconSize.roundToPx()
+                        lockIconMeasurable.measure(
+                            Constraints.fixed(width = lockIconSizeInt, height = lockIconSizeInt)
+                        )
+                    } else {
+                        lockIconMeasurable.measure(noMinConstraints)
+                    }
                 val lockIconBounds =
-                    IntRect(
-                        left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
-                        top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
-                        right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
-                        bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
-                    )
+                    if (communalSettingsInteractor.isV2FlagEnabled()) {
+                        val lockIconDistanceFromBottom =
+                            min(
+                                (constraints.maxHeight * lockIconPercentDistanceFromBottom)
+                                    .roundToInt(),
+                                lockIconMinDistanceFromBottom.roundToPx(),
+                            )
+                        val x = constraints.maxWidth / 2 - lockIconPlaceable.width / 2
+                        val y =
+                            constraints.maxHeight -
+                                lockIconDistanceFromBottom -
+                                lockIconPlaceable.height
+                        IntRect(
+                            left = x,
+                            top = y,
+                            right = x + lockIconPlaceable.width,
+                            bottom = y + lockIconPlaceable.height,
+                        )
+                    } else {
+                        IntRect(
+                            left = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Left],
+                            top = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Top],
+                            right = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Right],
+                            bottom = lockIconPlaceable[BlueprintAlignmentLines.LockIcon.Bottom],
+                        )
+                    }
 
                 val bottomAreaPlaceable = bottomAreaMeasurable.measure(noMinConstraints)
 
@@ -129,12 +173,17 @@
 
                     val bottomAreaTop = constraints.maxHeight - bottomAreaPlaceable.height
                     bottomAreaPlaceable.place(x = 0, y = bottomAreaTop)
+
+                    val screensaverButtonPaddingInt = screensaverButtonPadding.roundToPx()
                     screensaverButtonPlaceable?.place(
                         x =
                             constraints.maxWidth -
                                 screensaverButtonSizeInt -
-                                Dimensions.ItemSpacing.roundToPx(),
-                        y = lockIconBounds.top,
+                                screensaverButtonPaddingInt,
+                        y =
+                            constraints.maxHeight -
+                                screensaverButtonSizeInt -
+                                screensaverButtonPaddingInt,
                     )
                 }
             }
@@ -142,6 +191,12 @@
     }
 
     companion object {
-        val screensaverButtonSize: Dp = 64.dp
+        private val screensaverButtonSize: Dp = 64.dp
+        private val screensaverButtonPadding: Dp = 24.dp
+        // TODO(b/382739998): Remove these hardcoded values once lock icon size and bottom area
+        // position are sorted.
+        private val lockIconSize: Dp = 54.dp
+        private val lockIconPercentDistanceFromBottom = 0.1f
+        private val lockIconMinDistanceFromBottom = 70.dp
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 5dbedc7..068df8e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -76,6 +76,8 @@
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.foundation.text.AutoSize
+import androidx.compose.foundation.text.BasicText
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
@@ -110,6 +112,7 @@
 import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -757,10 +760,12 @@
 private fun HorizontalGridWrapper(
     minContentPadding: PaddingValues,
     gridState: LazyGridState,
+    dragDropState: GridDragDropState?,
     setContentOffset: (offset: Offset) -> Unit,
     modifier: Modifier = Modifier,
     content: LazyGridScope.(sizeInfo: SizeInfo?) -> Unit,
 ) {
+    val isDragging = dragDropState?.draggingItemKey != null
     if (communalResponsiveGrid()) {
         val flingBehavior =
             rememberSnapFlingBehavior(lazyGridState = gridState, snapPosition = SnapPosition.Start)
@@ -773,6 +778,10 @@
             minHorizontalArrangement = Dimensions.ItemSpacing,
             minVerticalArrangement = Dimensions.ItemSpacing,
             setContentOffset = setContentOffset,
+            // Temporarily disable user gesture scrolling while dragging a widget to prevent
+            // conflicts between the drag and scroll gestures. Programmatic scrolling remains
+            // enabled to allow dragging a widget beyond the visible boundaries.
+            userScrollEnabled = !isDragging,
             content = content,
         )
     } else {
@@ -791,6 +800,10 @@
             contentPadding = minContentPadding,
             horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
             verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
+            // Temporarily disable user gesture scrolling while dragging a widget to prevent
+            // conflicts between the drag and scroll gestures. Programmatic scrolling remains
+            // enabled to allow dragging a widget beyond the visible boundaries.
+            userScrollEnabled = !isDragging,
         ) {
             content(null)
         }
@@ -860,6 +873,7 @@
     HorizontalGridWrapper(
         modifier = gridModifier,
         gridState = gridState,
+        dragDropState = dragDropState,
         minContentPadding = minContentPadding,
         setContentOffset = setContentOffset,
     ) { sizeInfo ->
@@ -931,7 +945,9 @@
                         Modifier.requiredSize(dpSize)
                             .thenIf(!isItemDragging) {
                                 Modifier.animateItem(
-                                    placementSpec = spring(stiffness = Spring.StiffnessMediumLow)
+                                    placementSpec = spring(stiffness = Spring.StiffnessMediumLow),
+                                    // See b/376495198 - not supported with AndroidView
+                                    fadeOutSpec = null,
                                 )
                             }
                             .thenIf(isItemDragging) { Modifier.zIndex(1f) },
@@ -980,11 +996,14 @@
                     size = size,
                     selected = false,
                     modifier =
-                        Modifier.requiredSize(dpSize).animateItem().thenIf(
-                            communalResponsiveGrid()
-                        ) {
-                            Modifier.graphicsLayer { alpha = itemAlpha?.value ?: 1f }
-                        },
+                        Modifier.requiredSize(dpSize)
+                            .animateItem(
+                                // See b/376495198 - not supported with AndroidView
+                                fadeOutSpec = null
+                            )
+                            .thenIf(communalResponsiveGrid()) {
+                                Modifier.graphicsLayer { alpha = itemAlpha?.value ?: 1f }
+                            },
                     index = index,
                     contentListState = contentListState,
                     interactionHandler = interactionHandler,
@@ -1005,8 +1024,11 @@
     val colors = MaterialTheme.colorScheme
     Card(
         modifier = Modifier.height(hubDimensions.GridHeight).padding(contentPadding),
-        colors = CardDefaults.cardColors(containerColor = Color.Transparent),
-        border = BorderStroke(3.adjustedDp, colors.secondary),
+        colors =
+            CardDefaults.cardColors(
+                containerColor = colors.primary,
+                contentColor = colors.onPrimary,
+            ),
         shape = RoundedCornerShape(size = 80.adjustedDp),
     ) {
         Column(
@@ -1016,24 +1038,28 @@
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
             val titleForEmptyStateCTA = stringResource(R.string.title_for_empty_state_cta)
-            Text(
+            BasicText(
                 text = titleForEmptyStateCTA,
-                style = MaterialTheme.typography.displaySmall,
-                textAlign = TextAlign.Center,
-                color = colors.onPrimary,
+                style =
+                    MaterialTheme.typography.displaySmall.merge(
+                        color = colors.onPrimary,
+                        textAlign = TextAlign.Center,
+                    ),
+                autoSize = AutoSize.StepBased(maxFontSize = 36.sp, stepSize = 0.1.sp),
                 modifier =
                     Modifier.focusable().semantics(mergeDescendants = true) {
                         contentDescription = titleForEmptyStateCTA
                         heading()
                     },
             )
+
             Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
                 Button(
                     modifier = Modifier.height(56.dp),
                     colors =
                         ButtonDefaults.buttonColors(
-                            containerColor = colors.primary,
-                            contentColor = colors.onPrimary,
+                            containerColor = colors.primaryContainer,
+                            contentColor = colors.onPrimaryContainer,
                         ),
                     onClick = { viewModel.onOpenWidgetEditor(shouldOpenWidgetPickerOnStart = true) },
                 ) {
@@ -1694,23 +1720,29 @@
 private fun UmoLegacy(viewModel: BaseCommunalViewModel, modifier: Modifier = Modifier) {
     AndroidView(
         modifier =
-            modifier.pointerInput(Unit) {
-                detectHorizontalDragGestures { change, _ ->
-                    change.consume()
-                    val upTime = SystemClock.uptimeMillis()
-                    val event =
-                        MotionEvent.obtain(
-                            upTime,
-                            upTime,
-                            MotionEvent.ACTION_MOVE,
-                            change.position.x,
-                            change.position.y,
-                            0,
-                        )
-                    viewModel.mediaHost.hostView.dispatchTouchEvent(event)
-                    event.recycle()
-                }
-            },
+            modifier
+                .clip(
+                    shape =
+                        RoundedCornerShape(dimensionResource(system_app_widget_background_radius))
+                )
+                .background(MaterialTheme.colorScheme.primary)
+                .pointerInput(Unit) {
+                    detectHorizontalDragGestures { change, _ ->
+                        change.consume()
+                        val upTime = SystemClock.uptimeMillis()
+                        val event =
+                            MotionEvent.obtain(
+                                upTime,
+                                upTime,
+                                MotionEvent.ACTION_MOVE,
+                                change.position.x,
+                                change.position.y,
+                                0,
+                            )
+                        viewModel.mediaHost.hostView.dispatchTouchEvent(event)
+                        event.recycle()
+                    }
+                },
         factory = { _ ->
             viewModel.mediaHost.hostView.apply {
                 layoutParams =
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index a88ad94..88b6510 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -66,7 +66,6 @@
             colors = communalColors,
             content = communalContent,
             viewModel = contentViewModel,
-            modifier = modifier.horizontalNestedScrollToScene(),
         )
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
index 5c7ca97..0344ab8 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
@@ -38,7 +38,6 @@
 import com.android.compose.modifiers.thenIf
 import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
 import com.android.systemui.keyguard.ui.composable.blueprint.rememberBurnIn
 import com.android.systemui.keyguard.ui.composable.modifier.burnInAware
@@ -90,14 +89,10 @@
 ) {
 
     init {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            throw IllegalStateException("this requires MigrateClocksToBlueprint.isEnabled")
-        }
         // This scene container section moves the NSSL to the SharedNotificationContainer.
         // This also requires that SharedNotificationContainer gets moved to the
         // SceneWindowRootView by the SceneWindowRootViewBinder. Prior to Scene Container,
-        // but when the KeyguardShadeMigrationNssl flag is enabled, NSSL is moved into this
-        // container by the NotificationStackScrollLayoutSection.
+        // NSSL is moved into this container by the NotificationStackScrollLayoutSection.
         // Ensure stackScrollLayout is a child of sharedNotificationContainer.
 
         if (stackScrollLayout.parent != sharedNotificationContainer) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
index db33e7c..79cf24b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt
@@ -35,9 +35,8 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.compose.animation.scene.ContentScope
 import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
-import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.SceneTransitionLayout
 import com.android.compose.modifiers.thenIf
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
 import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene
@@ -61,7 +60,7 @@
     private val clockInteractor: KeyguardClockInteractor,
 ) {
     @Composable
-    fun SceneScope.DefaultClockLayout(
+    fun ContentScope.DefaultClockLayout(
         smartSpacePaddingTop: (Resources) -> Int,
         isShadeLayoutWide: Boolean,
         modifier: Modifier = Modifier,
@@ -95,7 +94,7 @@
         }
 
         Column(modifier) {
-            SceneTransitionLayout(state) {
+            NestedSceneTransitionLayout(state, Modifier) {
                 scene(splitShadeLargeClockScene) {
                     LargeClockWithSmartSpace(
                         smartSpacePaddingTop = smartSpacePaddingTop,
@@ -134,7 +133,7 @@
     }
 
     @Composable
-    private fun SceneScope.SmallClockWithSmartSpace(
+    private fun ContentScope.SmallClockWithSmartSpace(
         smartSpacePaddingTop: (Resources) -> Int,
         modifier: Modifier = Modifier,
     ) {
@@ -159,7 +158,7 @@
     }
 
     @Composable
-    private fun SceneScope.LargeClockWithSmartSpace(
+    private fun ContentScope.LargeClockWithSmartSpace(
         smartSpacePaddingTop: (Resources) -> Int,
         shouldOffSetClockToOneHalf: Boolean = false,
     ) {
@@ -200,7 +199,7 @@
     }
 
     @Composable
-    private fun SceneScope.WeatherLargeClockWithSmartSpace(
+    private fun ContentScope.WeatherLargeClockWithSmartSpace(
         smartSpacePaddingTop: (Resources) -> Int,
         modifier: Modifier = Modifier,
     ) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
index b54de78..58bfd08 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/Notifications.kt
@@ -88,7 +88,6 @@
 import com.android.compose.animation.scene.ContentScope
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.LowestZIndexContentPicker
-import com.android.compose.animation.scene.NestedScrollBehavior
 import com.android.compose.animation.scene.SceneTransitionLayoutState
 import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.modifiers.thenIf
@@ -236,10 +235,7 @@
                     )
                 }
                 .thenIf(isHeadsUp) {
-                    Modifier.verticalNestedScrollToScene(
-                            bottomBehavior = NestedScrollBehavior.EdgeAlways
-                        )
-                        .nestedScroll(nestedScrollConnection)
+                    Modifier.nestedScroll(nestedScrollConnection)
                         .scrollable(orientation = Orientation.Vertical, state = scrollableState)
                 },
     )
@@ -344,11 +340,12 @@
     // set the bounds to null when the scrim disappears
     DisposableEffect(Unit) { onDispose { viewModel.onScrimBoundsChanged(null) } }
 
-    val minScrimTop = with(density) { ShadeHeader.Dimensions.CollapsedHeight.toPx() }
+    // Top position if the scrim, when it is fully expanded.
+    val minScrimTop = ShadeHeader.Dimensions.CollapsedHeight
 
     // The minimum offset for the scrim. The scrim is considered fully expanded when it
     // is at this offset.
-    val minScrimOffset: () -> Float = { minScrimTop - maxScrimTop() }
+    val minScrimOffset: () -> Float = { with(density) { minScrimTop.toPx() } - maxScrimTop() }
 
     // The height of the scrim visible on screen when it is in its resting (collapsed) state.
     val minVisibleScrimHeight: () -> Float = {
@@ -567,15 +564,12 @@
                     }
                     .thenIf(shouldShowScrim) { Modifier.background(scrimBackgroundColor) }
                     .thenIf(shouldFillMaxSize) { Modifier.fillMaxSize() }
+                    .thenIf(supportNestedScrolling) { Modifier.padding(bottom = minScrimTop) }
                     .debugBackground(viewModel, DEBUG_BOX_COLOR)
         ) {
             Column(
                 modifier =
-                    Modifier.verticalNestedScrollToScene(
-                            topBehavior = NestedScrollBehavior.EdgeWithPreview,
-                            isExternalOverscrollGesture = { isCurrentGestureOverscroll.value },
-                        )
-                        .thenIf(supportNestedScrolling) {
+                    Modifier.thenIf(supportNestedScrolling) {
                             Modifier.nestedScroll(scrimNestedScrollConnection)
                         }
                         .stackVerticalOverscroll(coroutineScope) { scrollState.canScrollForward }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index 2af5ffa..5790c4a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -19,6 +19,7 @@
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.layoutId
 import com.android.compose.animation.scene.ContentScope
@@ -84,7 +85,11 @@
                 viewModel.notificationsPlaceholderViewModelFactory.create()
             }
 
-        OverlayShade(modifier = modifier, onScrimClicked = viewModel::onScrimClicked) {
+        OverlayShade(
+            panelAlignment = Alignment.TopStart,
+            modifier = modifier,
+            onScrimClicked = viewModel::onScrimClicked,
+        ) {
             Column {
                 if (viewModel.showHeader) {
                     val burnIn = rememberBurnIn(clockInteractor)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 6591a75..75226b3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -26,12 +26,12 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
 import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.safeContentPadding
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.Divider
+import androidx.compose.material3.HorizontalDivider
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
@@ -47,7 +47,6 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.android.compose.theme.colorAttr
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.people.ui.viewmodel.PeopleTileViewModel
 import com.android.systemui.people.ui.viewmodel.PeopleViewModel
@@ -75,13 +74,7 @@
         }
     }
 
-    // Make sure to use the Android colors and not the default Material3 colors to have the exact
-    // same colors as the View implementation.
-    Surface(
-        color = colorAttr(com.android.internal.R.attr.colorBackground),
-        contentColor = colorAttr(com.android.internal.R.attr.textColorPrimary),
-        modifier = Modifier.fillMaxSize(),
-    ) {
+    Surface(color = MaterialTheme.colorScheme.background, modifier = Modifier.fillMaxSize()) {
         if (priorityTiles.isNotEmpty() || recentTiles.isNotEmpty()) {
             PeopleScreenWithConversations(priorityTiles, recentTiles, viewModel.onTileClicked)
         } else {
@@ -97,7 +90,7 @@
     onTileClicked: (PeopleTileViewModel) -> Unit,
 ) {
     Column(
-        Modifier.fillMaxSize().safeContentPadding().sysuiResTag("top_level_with_conversations")
+        Modifier.fillMaxSize().safeDrawingPadding().sysuiResTag("top_level_with_conversations")
     ) {
         Column(
             Modifier.fillMaxWidth().padding(PeopleSpacePadding),
@@ -151,17 +144,14 @@
         stringResource(headerTextResource),
         Modifier.padding(start = 16.dp),
         style = MaterialTheme.typography.labelLarge,
-        color = colorAttr(com.android.internal.R.attr.colorAccentPrimaryVariant),
+        color = MaterialTheme.colorScheme.primary,
     )
 
     Spacer(Modifier.height(10.dp))
 
     tiles.forEachIndexed { index, tile ->
         if (index > 0) {
-            Divider(
-                color = colorAttr(com.android.internal.R.attr.colorBackground),
-                thickness = 2.dp,
-            )
+            HorizontalDivider(color = MaterialTheme.colorScheme.background, thickness = 2.dp)
         }
 
         key(tile.key.toString()) {
@@ -187,8 +177,7 @@
     val bottomCornerRadius = if (withBottomCornerRadius) cornerRadius else 0.dp
 
     Surface(
-        color = colorAttr(com.android.internal.R.attr.colorSurface),
-        contentColor = colorAttr(com.android.internal.R.attr.textColorPrimary),
+        color = MaterialTheme.colorScheme.secondaryContainer,
         shape =
             RoundedCornerShape(
                 topStart = topCornerRadius,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 9f582bc..527314d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -25,12 +25,11 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.safeContentPadding
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.Button
-import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
@@ -42,13 +41,12 @@
 import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.dp
-import com.android.compose.theme.colorAttr
 import com.android.systemui.res.R
 
 @Composable
 internal fun PeopleScreenEmpty(onGotItClicked: () -> Unit) {
     Column(
-        Modifier.fillMaxSize().safeContentPadding().padding(PeopleSpacePadding),
+        Modifier.fillMaxSize().safeDrawingPadding().padding(PeopleSpacePadding),
         horizontalAlignment = Alignment.CenterHorizontally,
     ) {
         Text(
@@ -69,15 +67,7 @@
         ExampleTile()
         Spacer(Modifier.weight(1f))
 
-        Button(
-            onGotItClicked,
-            Modifier.fillMaxWidth().defaultMinSize(minHeight = 56.dp),
-            colors =
-                ButtonDefaults.buttonColors(
-                    containerColor = colorAttr(com.android.internal.R.attr.colorAccentPrimary),
-                    contentColor = colorAttr(com.android.internal.R.attr.textColorOnAccent),
-                ),
-        ) {
+        Button(onGotItClicked, Modifier.fillMaxWidth().defaultMinSize(minHeight = 56.dp)) {
             Text(stringResource(R.string.got_it))
         }
     }
@@ -87,8 +77,7 @@
 private fun ExampleTile() {
     Surface(
         shape = RoundedCornerShape(28.dp),
-        color = colorAttr(com.android.internal.R.attr.colorSurface),
-        contentColor = colorAttr(com.android.internal.R.attr.textColorPrimary),
+        color = MaterialTheme.colorScheme.secondaryContainer,
     ) {
         Row(
             Modifier.padding(vertical = 20.dp, horizontal = 16.dp),
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index b1a1945..3327fc0 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -27,17 +27,17 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.requiredHeightIn
+import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.compose.animation.scene.ContentScope
-import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.battery.BatteryMeterViewController
@@ -46,20 +46,18 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.rememberViewModel
 import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotificationSpace
-import com.android.systemui.plugins.qs.TileDetailsViewModel
 import com.android.systemui.qs.composefragment.ui.GridAnchor
 import com.android.systemui.qs.flags.QsDetailedView
 import com.android.systemui.qs.panels.ui.compose.EditMode
 import com.android.systemui.qs.panels.ui.compose.TileDetails
 import com.android.systemui.qs.panels.ui.compose.TileGrid
 import com.android.systemui.qs.panels.ui.compose.toolbar.Toolbar
-import com.android.systemui.qs.ui.composable.QuickSettingsShade.Dimensions.GridMaxHeight
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeOverlayActionsViewModel
 import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeOverlayContentViewModel
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.ui.composable.Overlay
-import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
+import com.android.systemui.shade.ui.composable.CollapsedShadeHeader
 import com.android.systemui.shade.ui.composable.OverlayShade
 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
@@ -99,14 +97,17 @@
         val viewModel =
             rememberViewModel("QuickSettingsShadeOverlay") { contentViewModelFactory.create() }
 
-        OverlayShade(modifier = modifier, onScrimClicked = viewModel::onScrimClicked) {
+        OverlayShade(
+            panelAlignment = Alignment.TopEnd,
+            modifier = modifier,
+            onScrimClicked = viewModel::onScrimClicked,
+        ) {
             Column {
-                ExpandedShadeHeader(
+                CollapsedShadeHeader(
                     viewModelFactory = viewModel.shadeHeaderViewModelFactory,
                     createTintedIconManager = tintedIconManagerFactory::create,
                     createBatteryMeterViewController = batteryMeterViewControllerFactory::create,
                     statusBarIconController = statusBarIconController,
-                    modifier = Modifier.padding(QuickSettingsShade.Dimensions.Padding),
                 )
 
                 ShadeBody(viewModel = viewModel.quickSettingsContainerViewModel)
@@ -123,7 +124,7 @@
     }
 }
 
-// A sealed interface to represent the possible states of the `ShadeBody`
+// The possible states of the `ShadeBody`.
 sealed interface ShadeBodyState {
     data object Editing : ShadeBodyState
 
@@ -132,23 +133,19 @@
     data object Default : ShadeBodyState
 }
 
-// Function to map the current state of the `ShadeBody`
-fun checkQsState(isEditing: Boolean, tileDetails: TileDetailsViewModel?): ShadeBodyState {
-    if (isEditing) {
-        return ShadeBodyState.Editing
-    } else if (tileDetails != null && QsDetailedView.isEnabled) {
-        return ShadeBodyState.TileDetails
-    }
-    return ShadeBodyState.Default
-}
-
 @Composable
-fun SceneScope.ShadeBody(viewModel: QuickSettingsContainerViewModel) {
+fun ContentScope.ShadeBody(viewModel: QuickSettingsContainerViewModel) {
     val isEditing by viewModel.editModeViewModel.isEditing.collectAsStateWithLifecycle()
-    val tileDetails = viewModel.detailsViewModel.activeTileDetails
+    val tileDetails =
+        if (QsDetailedView.isEnabled) viewModel.detailsViewModel.activeTileDetails else null
 
     AnimatedContent(
-        targetState = checkQsState(isEditing, tileDetails),
+        targetState =
+            when {
+                isEditing -> ShadeBodyState.Editing
+                tileDetails != null -> ShadeBodyState.TileDetails
+                else -> ShadeBodyState.Default
+            },
         transitionSpec = { fadeIn(tween(500)) togetherWith fadeOut(tween(500)) },
     ) { state ->
         when (state) {
@@ -174,36 +171,43 @@
 
 /** Column containing Brightness and QS tiles. */
 @Composable
-fun SceneScope.QuickSettingsLayout(
+fun ContentScope.QuickSettingsLayout(
     viewModel: QuickSettingsContainerViewModel,
     modifier: Modifier = Modifier,
 ) {
     Column(
         verticalArrangement = Arrangement.spacedBy(QuickSettingsShade.Dimensions.Padding),
         horizontalAlignment = Alignment.CenterHorizontally,
-        modifier =
-            modifier
-                .fillMaxWidth()
-                .padding(
-                    start = QuickSettingsShade.Dimensions.Padding,
-                    end = QuickSettingsShade.Dimensions.Padding,
-                    bottom = QuickSettingsShade.Dimensions.Padding / 2,
-                ),
+        modifier = modifier
+            .padding(
+                start = QuickSettingsShade.Dimensions.Padding,
+                end = QuickSettingsShade.Dimensions.Padding,
+                bottom = QuickSettingsShade.Dimensions.Padding,
+            ),
     ) {
-        Toolbar(viewModel.toolbarViewModelFactory)
-        BrightnessSliderContainer(
-            viewModel = viewModel.brightnessSliderViewModel,
+        Toolbar(
             modifier =
-                Modifier.fillMaxWidth().height(QuickSettingsShade.Dimensions.BrightnessSliderHeight),
+                Modifier.fillMaxWidth().requiredHeight(QuickSettingsShade.Dimensions.ToolbarHeight),
+            toolbarViewModelFactory = viewModel.toolbarViewModelFactory,
         )
-        Box(
-            modifier =
-                Modifier.requiredHeightIn(max = GridMaxHeight)
-                    .verticalNestedScrollToScene()
-                    .verticalScroll(rememberScrollState())
+        Column(
+            verticalArrangement = Arrangement.spacedBy(QuickSettingsShade.Dimensions.Padding),
+            modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState()),
         ) {
-            GridAnchor()
-            TileGrid(viewModel = viewModel.tileGridViewModel, modifier = Modifier.fillMaxWidth())
+            BrightnessSliderContainer(
+                viewModel = viewModel.brightnessSliderViewModel,
+                containerColor = Color.Transparent,
+                modifier =
+                    Modifier.fillMaxWidth()
+                        .height(QuickSettingsShade.Dimensions.BrightnessSliderHeight),
+            )
+            Box {
+                GridAnchor()
+                TileGrid(
+                    viewModel = viewModel.tileGridViewModel,
+                    modifier = Modifier.fillMaxWidth(),
+                )
+            }
         }
     }
 }
@@ -212,7 +216,7 @@
 
     object Dimensions {
         val Padding = 16.dp
+        val ToolbarHeight = 48.dp
         val BrightnessSliderHeight = 64.dp
-        val GridMaxHeight = 420.dp
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index 55fafd5..ee8535e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -1,11 +1,8 @@
 package com.android.systemui.scene.ui.composable
 
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
-import com.android.compose.animation.scene.ProgressConverter
 import com.android.compose.animation.scene.TransitionKey
 import com.android.compose.animation.scene.transitions
-import com.android.systemui.bouncer.ui.composable.Bouncer
 import com.android.systemui.notifications.ui.composable.Notifications
 import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.Scenes
@@ -51,7 +48,6 @@
     interruptionHandler = SceneContainerInterruptionHandler
 
     // Overscroll progress starts linearly with some resistance (3f) and slowly approaches 0.2f
-    defaultOverscrollProgressConverter = ProgressConverter.tanh(maxProgress = 0.2f, tilt = 3f)
     defaultSwipeSpec = spring(stiffness = 300f, dampingRatio = 0.8f, visibilityThreshold = 0.5f)
 
     // Scene transitions
@@ -110,17 +106,13 @@
 
     // Overlay transitions
 
-    // TODO(b/376659778): Remove this transition once nested STLs are supported.
-    from(Scenes.Gone, to = Overlays.NotificationsShade) {
-        toNotificationsShadeTransition(translateClock = true)
-    }
     to(Overlays.NotificationsShade) { toNotificationsShadeTransition() }
     to(Overlays.QuickSettingsShade) { toQuickSettingsShadeTransition() }
     from(Overlays.NotificationsShade, to = Overlays.QuickSettingsShade) {
         notificationsShadeToQuickSettingsShadeTransition()
     }
     from(Scenes.Gone, to = Overlays.NotificationsShade, key = SlightlyFasterShadeCollapse) {
-        toNotificationsShadeTransition(translateClock = true, durationScale = 0.9)
+        toNotificationsShadeTransition(durationScale = 0.9)
     }
     from(Scenes.Gone, to = Overlays.QuickSettingsShade, key = SlightlyFasterShadeCollapse) {
         toQuickSettingsShadeTransition(durationScale = 0.9)
@@ -131,13 +123,4 @@
     from(Scenes.Lockscreen, to = Overlays.QuickSettingsShade, key = SlightlyFasterShadeCollapse) {
         toQuickSettingsShadeTransition(durationScale = 0.9)
     }
-
-    // Scene overscroll
-    // TODO(b/382477212) Remove STL Overscroll DSL
-    overscrollDisabled(Scenes.Gone, Orientation.Vertical)
-    overscrollDisabled(Scenes.Lockscreen, Orientation.Vertical)
-    overscrollDisabled(Scenes.Bouncer, Orientation.Vertical)
-    overscrollDisabled(Scenes.Shade, Orientation.Vertical)
-    overscrollDisabled(Overlays.NotificationsShade, Orientation.Vertical)
-    overscrollDisabled(Overlays.QuickSettingsShade, Orientation.Vertical)
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
index 6bdb363..3d62151 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/ToNotificationsShadeTransition.kt
@@ -29,10 +29,7 @@
 import com.android.systemui.shade.ui.composable.Shade
 import kotlin.time.Duration.Companion.milliseconds
 
-fun TransitionBuilder.toNotificationsShadeTransition(
-    translateClock: Boolean = false,
-    durationScale: Double = 1.0,
-) {
+fun TransitionBuilder.toNotificationsShadeTransition(durationScale: Double = 1.0) {
     spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
     swipeSpec =
         spring(
@@ -45,11 +42,6 @@
         elevateInContent = Overlays.NotificationsShade,
     )
     scaleSize(OverlayShade.Elements.Panel, height = 0f)
-    // TODO(b/376659778): This is a temporary hack to have a shared element transition with the
-    //  lockscreen clock. Remove once nested STLs are supported.
-    if (!translateClock) {
-        translate(ClockElementKeys.smallClockElementKey)
-    }
     // Avoid translating the status bar with the shade panel.
     translate(NotificationsShade.Elements.StatusBar)
     // Slide in the shade panel from the top edge.
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
index 8a5c96d..cfbe667 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt
@@ -20,6 +20,9 @@
 
 import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.rememberScrollableState
+import androidx.compose.foundation.gestures.scrollable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.ExperimentalLayoutApi
 import androidx.compose.foundation.layout.PaddingValues
@@ -41,30 +44,51 @@
 import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.unit.Velocity
 import androidx.compose.ui.unit.dp
+import com.android.compose.animation.scene.ContentScope
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.LowestZIndexContentPicker
-import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.effect.rememberOffsetOverscrollEffect
 import com.android.compose.windowsizeclass.LocalWindowSizeClass
 import com.android.systemui.res.R
 
 /** Renders a lightweight shade UI container, as an overlay. */
 @Composable
-fun SceneScope.OverlayShade(
+fun ContentScope.OverlayShade(
+    panelAlignment: Alignment,
     onScrimClicked: () -> Unit,
     modifier: Modifier = Modifier,
     content: @Composable () -> Unit,
 ) {
-    Box(modifier) {
+    // TODO(b/384653288) This should be removed when b/378470603 is done.
+    val idleEffect = rememberOffsetOverscrollEffect(Orientation.Vertical)
+    Box(
+        modifier
+            .overscroll(idleEffect)
+            .nestedScroll(
+                remember {
+                    object : NestedScrollConnection {
+                        override suspend fun onPreFling(available: Velocity): Velocity {
+                            return available
+                        }
+                    }
+                }
+            )
+            .scrollable(rememberScrollableState { 0f }, Orientation.Vertical, idleEffect)
+    ) {
         Scrim(onClicked = onScrimClicked)
 
-        Box(modifier = Modifier.fillMaxSize().panelPadding(), contentAlignment = Alignment.TopEnd) {
+        Box(modifier = Modifier.fillMaxSize().panelPadding(), contentAlignment = panelAlignment) {
             Panel(
                 modifier =
                     Modifier.element(OverlayShade.Elements.Panel)
@@ -77,7 +101,7 @@
 }
 
 @Composable
-private fun SceneScope.Scrim(onClicked: () -> Unit, modifier: Modifier = Modifier) {
+private fun ContentScope.Scrim(onClicked: () -> Unit, modifier: Modifier = Modifier) {
     Spacer(
         modifier =
             modifier
@@ -89,7 +113,7 @@
 }
 
 @Composable
-private fun SceneScope.Panel(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
+private fun ContentScope.Panel(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
     Box(modifier = modifier.clip(OverlayShade.Shapes.RoundedCornerPanel)) {
         Spacer(
             modifier =
@@ -180,7 +204,6 @@
 
     object Dimensions {
         val PanelCornerRadius = 46.dp
-        val OverscrollLimit = 32.dp
     }
 
     object Shapes {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 79fd1d7..aefe83b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -65,7 +65,6 @@
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.LowestZIndexContentPicker
-import com.android.compose.animation.scene.NestedScrollBehavior
 import com.android.compose.animation.scene.SceneScope
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
@@ -240,7 +239,7 @@
                 modifier = modifier,
                 shadeSession = shadeSession,
             )
-        is ShadeMode.Dual -> error("Dual shade is not yet implemented!")
+        is ShadeMode.Dual -> error("Dual shade is implemented separately as an overlay.")
     }
 }
 
@@ -400,10 +399,6 @@
                     .height(navBarHeight)
                     // Intercepts touches, prevents the scrollable container behind from scrolling.
                     .clickable(interactionSource = null, indication = null) { /* do nothing */ }
-                    .verticalNestedScrollToScene(
-                        topBehavior = NestedScrollBehavior.EdgeAlways,
-                        isExternalOverscrollGesture = { false },
-                    )
         ) {
             NotificationStackCutoffGuideline(
                 stackScrollView = notificationStackScrollView,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
index fa5f72b..1480db9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
@@ -37,12 +37,14 @@
 import androidx.compose.material3.Slider
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.State
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableFloatStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.CustomAccessibilityAction
@@ -66,6 +68,10 @@
 import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
 import com.android.systemui.lifecycle.rememberViewModel
 import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderState
+import kotlin.math.round
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
 
 @Composable
 fun VolumeSlider(
@@ -196,9 +202,17 @@
                 )
             }
         }
-
-    // Perform haptics due to UI composition
-    hapticsViewModel?.onValueChange(value)
+    var lastDiscreteStep by remember { mutableFloatStateOf(round(value)) }
+    LaunchedEffect(value) {
+        snapshotFlow { value }
+            .map { round(it) }
+            .filter { it != lastDiscreteStep }
+            .distinctUntilChanged()
+            .collect { discreteStep ->
+                lastDiscreteStep = discreteStep
+                hapticsViewModel?.onValueChange(discreteStep)
+            }
+    }
 
     PlatformSlider(
         modifier =
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index a4237f3..495fdaf 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -418,15 +418,11 @@
             return fromValue
         }
 
-        val overscrollSpec = transition.currentOverscrollSpec
         val progress =
-            when {
-                overscrollSpec == null -> {
-                    if (canOverflow) transition.progress
-                    else transition.progress.fastCoerceIn(0f, 1f)
-                }
-                overscrollSpec.content == transition.toContent -> 1f
-                else -> 0f
+            if (canOverflow) {
+                transition.progress
+            } else {
+                transition.progress.fastCoerceIn(0f, 1f)
             }
 
         return sharedValue.type.lerp(fromValue, toValue, progress)
@@ -438,7 +434,8 @@
             if (element != null) {
                 layoutImpl.elements[element]?.let { element ->
                     elementState(
-                        layoutImpl.state.transitionStates,
+                        listOf(layoutImpl.state.transitionStates),
+                        elementKey = element.key,
                         isInContent = { it in element.stateByContent },
                     )
                         as? TransitionState.Transition
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 9744424..6bb579d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -23,12 +23,13 @@
 import androidx.compose.ui.unit.round
 import androidx.compose.ui.util.fastCoerceIn
 import com.android.compose.animation.scene.content.Content
-import com.android.compose.animation.scene.content.state.TransitionState.DirectionProperties.Companion.DistanceUnspecified
+import com.android.compose.animation.scene.content.state.TransitionState.Companion.DistanceUnspecified
 import com.android.compose.nestedscroll.OnStopScope
 import com.android.compose.nestedscroll.PriorityNestedScrollConnection
 import com.android.compose.nestedscroll.ScrollController
 import com.android.compose.ui.util.SpaceVectorConverter
 import kotlin.math.absoluteValue
+import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.NonCancellable
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -76,8 +77,6 @@
     internal val layoutImpl: SceneTransitionLayoutImpl,
     internal val orientation: Orientation,
 ) : DraggableHandler {
-    internal val nestedScrollKey = Any()
-
     /** The [DraggableHandler] can only have one active [DragController] at a time. */
     private var dragController: DragControllerImpl? = null
 
@@ -359,13 +358,24 @@
             return swipeAnimation.animateOffset(velocity, targetContent)
         }
 
-        overscrollEffect.applyToFling(
-            velocity = velocity.toVelocity(),
-            performFling = {
-                val velocityLeft = it.toFloat()
-                swipeAnimation.animateOffset(velocityLeft, targetContent).toVelocity()
-            },
-        )
+        val overscrollCompletable = CompletableDeferred<Unit>()
+        try {
+            overscrollEffect.applyToFling(
+                velocity = velocity.toVelocity(),
+                performFling = {
+                    val velocityLeft = it.toFloat()
+                    swipeAnimation
+                        .animateOffset(
+                            velocityLeft,
+                            targetContent,
+                            overscrollCompletable = overscrollCompletable,
+                        )
+                        .toVelocity()
+                },
+            )
+        } finally {
+            overscrollCompletable.complete(Unit)
+        }
 
         return velocity
     }
@@ -452,41 +462,20 @@
 
 internal class NestedScrollHandlerImpl(
     private val draggableHandler: DraggableHandlerImpl,
-    internal var topOrLeftBehavior: NestedScrollBehavior,
-    internal var bottomOrRightBehavior: NestedScrollBehavior,
-    internal var isExternalOverscrollGesture: () -> Boolean,
     private val pointersInfoOwner: PointersInfoOwner,
 ) {
     val connection: PriorityNestedScrollConnection = nestedScrollConnection()
 
     private fun nestedScrollConnection(): PriorityNestedScrollConnection {
-        // If we performed a long gesture before entering priority mode, we would have to avoid
-        // moving on to the next scene.
-        var canChangeScene = false
-
         var lastPointersDown: PointersInfo.PointersDown? = null
 
-        fun shouldEnableSwipes(): Boolean {
-            return draggableHandler.layoutImpl
-                .contentForUserActions()
-                .shouldEnableSwipes(draggableHandler.orientation)
-        }
-
         return PriorityNestedScrollConnection(
             orientation = draggableHandler.orientation,
             canStartPreScroll = { _, _, _ -> false },
-            canStartPostScroll = { offsetAvailable, offsetBeforeStart, _ ->
-                val behavior: NestedScrollBehavior =
-                    when {
-                        offsetAvailable > 0f -> topOrLeftBehavior
-                        offsetAvailable < 0f -> bottomOrRightBehavior
-                        else -> return@PriorityNestedScrollConnection false
-                    }
+            canStartPostScroll = { offsetAvailable, _, _ ->
+                if (offsetAvailable == 0f) return@PriorityNestedScrollConnection false
 
-                val isZeroOffset =
-                    if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
-
-                val pointersDown: PointersInfo.PointersDown? =
+                lastPointersDown =
                     when (val info = pointersInfoOwner.pointersInfo()) {
                         PointersInfo.MouseWheel -> {
                             // Do not support mouse wheel interactions
@@ -496,24 +485,10 @@
                         is PointersInfo.PointersDown -> info
                         null -> null
                     }
-                lastPointersDown = pointersDown
 
-                when (behavior) {
-                    NestedScrollBehavior.EdgeNoPreview -> {
-                        canChangeScene = isZeroOffset
-                        isZeroOffset && shouldEnableSwipes()
-                    }
-
-                    NestedScrollBehavior.EdgeWithPreview -> {
-                        canChangeScene = isZeroOffset
-                        shouldEnableSwipes()
-                    }
-
-                    NestedScrollBehavior.EdgeAlways -> {
-                        canChangeScene = true
-                        shouldEnableSwipes()
-                    }
-                }
+                draggableHandler.layoutImpl
+                    .contentForUserActions()
+                    .shouldEnableSwipes(draggableHandler.orientation)
             },
             onStart = { firstScroll ->
                 scrollController(
@@ -522,7 +497,6 @@
                             pointersDown = lastPointersDown,
                             overSlop = firstScroll,
                         ),
-                    canChangeScene = canChangeScene,
                     pointersInfoOwner = pointersInfoOwner,
                 )
             },
@@ -532,7 +506,6 @@
 
 private fun scrollController(
     dragController: DragController,
-    canChangeScene: Boolean,
     pointersInfoOwner: PointersInfoOwner,
 ): ScrollController {
     return object : ScrollController {
@@ -546,14 +519,11 @@
         }
 
         override suspend fun OnStopScope.onStop(initialVelocity: Float): Float {
-            return dragController.onStop(
-                velocity = initialVelocity,
-                canChangeContent = canChangeScene,
-            )
+            return dragController.onStop(velocity = initialVelocity, canChangeContent = true)
         }
 
         override fun onCancel() {
-            dragController.onCancel(canChangeScene)
+            dragController.onCancel(canChangeContent = true)
         }
 
         /**
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index 07a19d8..b0d9fcd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -45,7 +45,11 @@
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.round
+import androidx.compose.ui.util.fastAll
+import androidx.compose.ui.util.fastAny
 import androidx.compose.ui.util.fastCoerceIn
+import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastForEachIndexed
 import androidx.compose.ui.util.fastForEachReversed
 import androidx.compose.ui.util.lerp
 import com.android.compose.animation.scene.content.Content
@@ -92,7 +96,17 @@
 
     /** The last and target state of this element in a given content. */
     @Stable
-    class State(val content: ContentKey) {
+    class State(
+        /**
+         * A list of contents where this element state finds itself in. The last content is the
+         * content of the STL which is actually responsible to compose and place this element. The
+         * other contents (if any) are the ancestors. The ancestors do not actually place this
+         * element but the element is part of the ancestors scene as part of a NestedSTL. The state
+         * can be accessed by ancestor transitions to read the properties of this element to compute
+         * transformations.
+         */
+        val contents: List<ContentKey>
+    ) {
         /**
          * The *target* state of this element in this content, i.e. the state of this element when
          * we are idle on this content.
@@ -158,7 +172,8 @@
     // layout/drawing.
     // TODO(b/341072461): Revert this and read the current transitions in ElementNode directly once
     // we can ensure that SceneTransitionLayoutImpl will compose new contents first.
-    val currentTransitionStates = layoutImpl.state.transitionStates
+    val currentTransitionStates = getAllNestedTransitionStates(layoutImpl)
+
     return thenIf(layoutImpl.state.isElevationPossible(content.key, key)) {
             Modifier.maybeElevateInContent(layoutImpl, content, key, currentTransitionStates)
         }
@@ -166,11 +181,26 @@
         .testTag(key.testTag)
 }
 
+/**
+ * Returns the transition states of all ancestors + the transition state of the current STL. The
+ * last element is the transition state of the local STL (the one with the highest nestingDepth).
+ *
+ * @return Each transition state of a STL is a List and this is a list of all the states.
+ */
+internal fun getAllNestedTransitionStates(
+    layoutImpl: SceneTransitionLayoutImpl
+): List<List<TransitionState>> {
+    return buildList {
+        layoutImpl.ancestors.fastForEach { add(it.layoutImpl.state.transitionStates) }
+        add(layoutImpl.state.transitionStates)
+    }
+}
+
 private fun Modifier.maybeElevateInContent(
     layoutImpl: SceneTransitionLayoutImpl,
     content: Content,
     key: ElementKey,
-    transitionStates: List<TransitionState>,
+    transitionStates: List<List<TransitionState>>,
 ): Modifier {
     fun isSharedElement(
         stateByContent: Map<ContentKey, Element.State>,
@@ -192,12 +222,12 @@
         content.containerState,
         enabled = {
             val stateByContent = layoutImpl.elements.getValue(key).stateByContent
-            val state = elementState(transitionStates, isInContent = { it in stateByContent })
+            val state = elementState(transitionStates, key, isInContent = { it in stateByContent })
 
             state is TransitionState.Transition &&
                 state.transformationSpec
                     .transformations(key, content.key)
-                    .shared
+                    ?.shared
                     ?.transformation
                     ?.elevateInContent == content.key &&
                 isSharedElement(stateByContent, state) &&
@@ -218,7 +248,7 @@
  */
 internal data class ElementModifier(
     internal val layoutImpl: SceneTransitionLayoutImpl,
-    private val currentTransitionStates: List<TransitionState>,
+    private val currentTransitionStates: List<List<TransitionState>>,
     internal val content: Content,
     internal val key: ElementKey,
 ) : ModifierNodeElement<ElementNode>() {
@@ -232,7 +262,7 @@
 
 internal class ElementNode(
     private var layoutImpl: SceneTransitionLayoutImpl,
-    private var currentTransitionStates: List<TransitionState>,
+    private var currentTransitionStates: List<List<TransitionState>>,
     private var content: Content,
     private var key: ElementKey,
 ) : Modifier.Node(), DrawModifierNode, ApproachLayoutModifierNode, TraversableNode {
@@ -257,10 +287,15 @@
         _element = element
         addToRenderAuthority(element)
         if (!element.stateByContent.contains(content.key)) {
-            val elementState = Element.State(content.key)
+            val contents = buildList {
+                layoutImpl.ancestors.fastForEach { add(it.inContent) }
+                add(content.key)
+            }
+
+            val elementState = Element.State(contents)
             element.stateByContent[content.key] = elementState
 
-            layoutImpl.ancestorContentKeys.forEach { element.stateByContent[it] = elementState }
+            layoutImpl.ancestors.fastForEach { element.stateByContent[it.inContent] = elementState }
         }
     }
 
@@ -273,7 +308,7 @@
             // this element was composed multiple times in the same content.
             val nCodeLocations = stateInContent.nodes.size
             if (nCodeLocations != 1 || !stateInContent.nodes.contains(this@ElementNode)) {
-                error("$key was composed $nCodeLocations times in ${stateInContent.content}")
+                error("$key was composed $nCodeLocations times in ${stateInContent.contents}")
             }
         }
     }
@@ -288,12 +323,12 @@
     }
 
     private fun addToRenderAuthority(element: Element) {
-        val nestingDepth = layoutImpl.ancestorContentKeys.size
+        val nestingDepth = layoutImpl.ancestors.size
         element.renderAuthority[nestingDepth] = content.key
     }
 
     private fun removeFromRenderAuthority() {
-        val nestingDepth = layoutImpl.ancestorContentKeys.size
+        val nestingDepth = layoutImpl.ancestors.size
         if (element.renderAuthority[nestingDepth] == content.key) {
             element.renderAuthority.remove(nestingDepth)
         }
@@ -305,7 +340,7 @@
 
     fun update(
         layoutImpl: SceneTransitionLayoutImpl,
-        currentTransitionStates: List<TransitionState>,
+        currentTransitionStates: List<List<TransitionState>>,
         content: Content,
         key: ElementKey,
     ) {
@@ -326,7 +361,7 @@
     override fun isMeasurementApproachInProgress(lookaheadSize: IntSize): Boolean {
         // TODO(b/324191441): Investigate whether making this check more complex (checking if this
         // element is shared or transformed) would lead to better performance.
-        return layoutImpl.state.isTransitioning()
+        return isAnyStateTransitioning()
     }
 
     override fun Placeable.PlacementScope.isPlacementApproachInProgress(
@@ -334,7 +369,12 @@
     ): Boolean {
         // TODO(b/324191441): Investigate whether making this check more complex (checking if this
         // element is shared or transformed) would lead to better performance.
-        return layoutImpl.state.isTransitioning()
+        return isAnyStateTransitioning()
+    }
+
+    private fun isAnyStateTransitioning(): Boolean {
+        return layoutImpl.state.isTransitioning() ||
+            layoutImpl.ancestors.fastAny { it.layoutImpl.state.isTransitioning() }
     }
 
     @ExperimentalComposeUiApi
@@ -372,7 +412,7 @@
             // This is the case if for example a transition between two overlays is ongoing where
             // sharedElement isn't part of either but the element is still rendered as part of
             // the underlying scene that is currently not being transitioned.
-            val currentState = currentTransitionStates.last()
+            val currentState = currentTransitionStates.last().last()
             val shouldPlaceInThisContent =
                 elementContentWhenIdle(
                     layoutImpl,
@@ -388,32 +428,6 @@
 
         val transition = elementState as? TransitionState.Transition
 
-        // If this element is not supposed to be laid out now, either because it is not part of any
-        // ongoing transition or the other content of its transition is overscrolling, then lay out
-        // the element normally and don't place it.
-        val overscrollContent = transition?.currentOverscrollSpec?.content
-        if (overscrollContent != null && overscrollContent != content.key) {
-            when (transition) {
-                is TransitionState.Transition.ChangeScene ->
-                    return doNotPlace(measurable, constraints)
-
-                // If we are overscrolling an overlay that does not contain an element that is in
-                // the current scene, place it in that scene otherwise the element won't be placed
-                // at all.
-                is TransitionState.Transition.ShowOrHideOverlay,
-                is TransitionState.Transition.ReplaceOverlay -> {
-                    if (
-                        content.key == transition.currentScene &&
-                            overscrollContent !in element.stateByContent
-                    ) {
-                        return placeNormally(measurable, constraints)
-                    } else {
-                        return doNotPlace(measurable, constraints)
-                    }
-                }
-            }
-        }
-
         val placeable =
             measure(layoutImpl, element, transition, stateInContent, measurable, constraints)
         stateInContent.lastSize = placeable.size()
@@ -474,7 +488,7 @@
                     element,
                     transition,
                     contentValue = { it.targetOffset },
-                    transformation = { it.offset },
+                    transformation = { it?.offset },
                     currentValue = { currentOffset },
                     isSpecified = { it != Offset.Unspecified },
                     ::lerp,
@@ -618,8 +632,7 @@
                 }
             }
 
-            pruneForContent(stateInContent.content)
-            layoutImpl.ancestorContentKeys.forEach { content -> pruneForContent(content) }
+            stateInContent.contents.fastForEach { pruneForContent(it) }
         }
     }
 }
@@ -628,9 +641,10 @@
 private fun elementState(
     layoutImpl: SceneTransitionLayoutImpl,
     element: Element,
-    transitionStates: List<TransitionState>,
+    transitionStates: List<List<TransitionState>>,
 ): TransitionState? {
-    val state = elementState(transitionStates, isInContent = { it in element.stateByContent })
+    val state =
+        elementState(transitionStates, element.key, isInContent = { it in element.stateByContent })
 
     val transition = state as? TransitionState.Transition
     val previousTransition = element.lastTransition
@@ -651,23 +665,48 @@
 }
 
 internal inline fun elementState(
-    transitionStates: List<TransitionState>,
+    transitionStates: List<List<TransitionState>>,
+    elementKey: ElementKey,
     isInContent: (ContentKey) -> Boolean,
 ): TransitionState? {
-    val lastState = transitionStates.last()
-    if (lastState is TransitionState.Idle) {
-        check(transitionStates.size == 1)
-        return lastState
-    }
+    // transitionStates is a list of all ancestor transition states + transitionState of the local
+    // STL. By traversing the list in normal order we by default prioritize the transitionState of
+    // the highest ancestor if it is running and has a transformation for this element.
+    transitionStates.fastForEachIndexed { index, states ->
+        if (index < transitionStates.size - 1) {
+            // Check if any ancestor runs a transition that has a transformation for the element
+            states.fastForEachReversed { state ->
+                if (
+                    state is TransitionState.Transition &&
+                        (state.transformationSpec.hasTransformation(
+                            elementKey,
+                            state.fromContent,
+                        ) ||
+                            state.transformationSpec.hasTransformation(elementKey, state.toContent))
+                ) {
+                    return state
+                }
+            }
+        } else {
+            // the last state of the list, is the state of the local STL
+            val lastState = states.last()
+            if (lastState is TransitionState.Idle) {
+                check(states.size == 1)
+                return lastState
+            }
 
-    // Find the last transition with a content that contains the element.
-    transitionStates.fastForEachReversed { state ->
-        val transition = state as TransitionState.Transition
-        if (isInContent(transition.fromContent) || isInContent(transition.toContent)) {
-            return transition
+            // Find the last transition with a content that contains the element.
+            states.fastForEachReversed { state ->
+                val transition = state as TransitionState.Transition
+                if (isInContent(transition.fromContent) || isInContent(transition.toContent)) {
+                    return transition
+                }
+            }
         }
     }
-
+    // We are running a transition where both from and to don't contain the element. The element
+    // may still be rendered as e.g. it can be part of a idle scene where two overlays are currently
+    // transitioning above it.
     return null
 }
 
@@ -732,7 +771,7 @@
         stateInContent.alphaInterruptionDelta = 0f
         stateInContent.scaleInterruptionDelta = Scale.Zero
 
-        if (!shouldPlaceElement(layoutImpl, stateInContent.content, element, transition)) {
+        if (!shouldPlaceElement(layoutImpl, stateInContent.contents.last(), element, transition)) {
             stateInContent.offsetBeforeInterruption = Offset.Unspecified
             stateInContent.alphaBeforeInterruption = Element.AlphaUnspecified
             stateInContent.scaleBeforeInterruption = Scale.Unspecified
@@ -746,7 +785,7 @@
 }
 
 /**
- * Reconcile the state of [element] in the formContent and toContent of [transition] so that the
+ * Reconcile the state of [element] in the fromContent and toContent of [transition] so that the
  * values before interruption have their expected values, taking shared transitions into account.
  *
  * @return the unique state this element had during [transition], `null` if it had multiple
@@ -904,7 +943,7 @@
     // If the element is shared, also set the delta on the other content so that it is used by that
     // content if we start overscrolling it and change the content where the element is placed.
     val otherContent =
-        if (stateInContent.content == transition.fromContent) transition.toContent
+        if (stateInContent.contents.last() == transition.fromContent) transition.toContent
         else transition.fromContent
     val otherContentState = element.stateByContent[otherContent] ?: return
     if (isSharedElementEnabled(element.key, transition)) {
@@ -942,7 +981,8 @@
     if (
         content != transition.fromContent &&
             content != transition.toContent &&
-            (!isReplacingOverlay || content != transition.currentScene)
+            (!isReplacingOverlay || content != transition.currentScene) &&
+            transitionDoesNotInvolveAncestorContent(layoutImpl, transition)
     ) {
         return false
     }
@@ -964,6 +1004,15 @@
     return shouldPlaceSharedElement(layoutImpl, content, element.key, transition)
 }
 
+private fun transitionDoesNotInvolveAncestorContent(
+    layoutImpl: SceneTransitionLayoutImpl,
+    transition: TransitionState.Transition,
+): Boolean {
+    return layoutImpl.ancestors.fastAll {
+        it.inContent != transition.fromContent && it.inContent != transition.toContent
+    }
+}
+
 /**
  * Whether the element is opaque or not.
  *
@@ -994,7 +1043,7 @@
         return true
     }
 
-    return transition.transformationSpec.transformations(element.key, content.key).alpha == null
+    return transition.transformationSpec.transformations(element.key, content.key)?.alpha == null
 }
 
 /**
@@ -1018,7 +1067,7 @@
                 element,
                 transition,
                 contentValue = { 1f },
-                transformation = { it.alpha },
+                transformation = { it?.alpha },
                 currentValue = { 1f },
                 isSpecified = { true },
                 ::lerp,
@@ -1086,7 +1135,7 @@
             element,
             transition,
             contentValue = { it.targetSize },
-            transformation = { it.size },
+            transformation = { it?.size },
             currentValue = { measurable.measure(constraints).also { maybePlaceable = it }.size() },
             isSpecified = { it != Element.SizeUnspecified },
             ::lerp,
@@ -1119,7 +1168,6 @@
                 )
             },
         )
-
     return measurable.measure(
         Constraints.fixed(
             interruptedSize.width.coerceAtLeast(0),
@@ -1143,7 +1191,7 @@
             element,
             transition,
             contentValue = { Scale.Default },
-            transformation = { it.drawScale },
+            transformation = { it?.drawScale },
             currentValue = { Scale.Default },
             isSpecified = { true },
             ::lerp,
@@ -1231,7 +1279,8 @@
     element: Element,
     transition: TransitionState.Transition?,
     contentValue: (Element.State) -> T,
-    transformation: (ElementTransformations) -> TransformationWithRange<PropertyTransformation<T>>?,
+    transformation:
+        (ElementTransformations?) -> TransformationWithRange<PropertyTransformation<T>>?,
     currentValue: () -> T,
     isSpecified: (T) -> Boolean,
     lerp: (T, T, Float) -> T,
@@ -1256,54 +1305,7 @@
         return contentValue(currentContentState)
     }
 
-    val currentContent = currentContentState.content
-    if (transition is TransitionState.DirectionProperties) {
-        val overscroll = transition.currentOverscrollSpec
-        if (overscroll?.content == currentContent) {
-            val elementSpec =
-                overscroll.transformationSpec.transformations(element.key, currentContent)
-            val propertySpec = transformation(elementSpec) ?: return currentValue()
-            val overscrollState =
-                checkNotNull(if (currentContent == toContent) toState else fromState)
-            val idleValue = contentValue(overscrollState)
-            val targetValue =
-                with(
-                    propertySpec.transformation.requireInterpolatedTransformation(
-                        element,
-                        transition,
-                    ) {
-                        "Custom transformations in overscroll specs should not be possible"
-                    }
-                ) {
-                    layoutImpl.propertyTransformationScope.transform(
-                        currentContent,
-                        element.key,
-                        transition,
-                        idleValue,
-                    )
-                }
-
-            // Make sure we don't read progress if values are the same and we don't need to
-            // interpolate, so we don't invalidate the phase where this is read.
-            if (targetValue == idleValue) {
-                return targetValue
-            }
-
-            // TODO(b/290184746): Make sure that we don't overflow transformations associated to a
-            // range.
-            val directionSign = if (transition.isUpOrLeft) -1 else 1
-            val isToContent = overscroll.content == transition.toContent
-            val linearProgress = transition.progress.let { if (isToContent) it - 1f else it }
-            val progressConverter =
-                overscroll.progressConverter
-                    ?: layoutImpl.state.transitions.defaultProgressConverter
-            val progress = directionSign * progressConverter.convert(linearProgress)
-            val rangeProgress = propertySpec.range?.progress(progress) ?: progress
-
-            // Interpolate between the value at rest and the over scrolled value.
-            return lerp(idleValue, targetValue, rangeProgress)
-        }
-    }
+    val currentContent = currentContentState.contents.last()
 
     // The element is shared: interpolate between the value in fromContent and the value in
     // toContent.
@@ -1338,23 +1340,52 @@
         }
     }
 
-    // Get the transformed value, i.e. the target value at the beginning (for entering elements) or
-    // end (for leaving elements) of the transition.
-    val contentState =
-        checkNotNull(
-            when {
-                isSharedElement && currentContent == fromContent -> fromState
-                isSharedElement -> toState
-                currentSceneState != null && currentContent == transition.currentScene ->
-                    currentSceneState
-                else -> fromState ?: toState
-            }
-        )
-
     // The content for which we compute the transformation. Note that this is not necessarily
     // [currentContent] because [currentContent] could be a different content than the transition
-    // fromContent or toContent during interruptions.
-    val content = contentState.content
+    // fromContent or toContent during interruptions or when a ancestor transition is running.
+    val content: ContentKey
+    // Get the transformed value, i.e. the target value at the beginning (for entering elements) or
+    // end (for leaving elements) of the transition.
+    val contentState: Element.State
+    when {
+        isSharedElement -> {
+            content = currentContent
+            contentState = currentContentState
+        }
+        isAncestorTransition(layoutImpl, transition) -> {
+            if (
+                fromState != null &&
+                    transition.transformationSpec.hasTransformation(element.key, fromContent)
+            ) {
+                content = fromContent
+                contentState = fromState
+            } else if (
+                toState != null &&
+                    transition.transformationSpec.hasTransformation(element.key, toContent)
+            ) {
+                content = toContent
+                contentState = toState
+            } else {
+                throw IllegalStateException(
+                    "Ancestor transition is active but no transformation " +
+                        "spec was found. The ancestor transition should have only been selected " +
+                        "when a transformation for that element and content was defined."
+                )
+            }
+        }
+        currentSceneState != null && currentContent == transition.currentScene -> {
+            content = currentContent
+            contentState = currentSceneState
+        }
+        fromState != null -> {
+            content = fromContent
+            contentState = fromState
+        }
+        else -> {
+            content = toContent
+            contentState = toState!!
+        }
+    }
 
     val transformationWithRange =
         transformation(transition.transformationSpec.transformations(element.key, content))
@@ -1510,6 +1541,8 @@
         when {
             content == toContent -> true
             content == fromContent -> false
+            isAncestorTransition(layoutImpl, transition) ->
+                isEnteringAncestorTransition(layoutImpl, transition)
             content == transition.currentScene -> toState == null
             else -> content == toContent
         }
@@ -1520,6 +1553,22 @@
     }
 }
 
+private fun isAncestorTransition(
+    layoutImpl: SceneTransitionLayoutImpl,
+    transition: TransitionState.Transition,
+): Boolean {
+    return layoutImpl.ancestors.fastAny {
+        it.inContent == transition.fromContent || it.inContent == transition.toContent
+    }
+}
+
+private fun isEnteringAncestorTransition(
+    layoutImpl: SceneTransitionLayoutImpl,
+    transition: TransitionState.Transition
+): Boolean {
+    return layoutImpl.ancestors.fastAny { it.inContent == transition.toContent }
+}
+
 private inline fun <T> PropertyTransformation<T>.requireInterpolatedTransformation(
     element: Element,
     transition: TransitionState.Transition,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index 17510c7..c10a485 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -163,7 +163,7 @@
             // Important: Like in Modifier.element(), we read the transition states during
             // composition then pass them to Layout to make sure that composition sees new states
             // before layout and drawing.
-            val transitionStates = layoutImpl.state.transitionStates
+            val transitionStates = getAllNestedTransitionStates(layoutImpl)
             Layout { _, _ ->
                 // No need to measure or place anything.
                 val size =
@@ -186,7 +186,7 @@
     element: MovableElementKey,
 ): Boolean {
     return when (
-        val elementState = movableElementState(element, layoutImpl.state.transitionStates)
+        val elementState = movableElementState(element, getAllNestedTransitionStates(layoutImpl))
     ) {
         null ->
             movableElementContentWhenIdle(layoutImpl, element, layoutImpl.state.transitionState) ==
@@ -196,13 +196,7 @@
         is TransitionState.Transition -> {
             // During transitions, always compose movable elements in the scene picked by their
             // content picker.
-            shouldComposeMoveableElement(
-                layoutImpl,
-                content,
-                element,
-                elementState,
-                element.contentPicker.contents,
-            )
+            shouldComposeMoveableElement(layoutImpl, content, element, elementState)
         }
     }
 }
@@ -212,26 +206,7 @@
     content: ContentKey,
     elementKey: ElementKey,
     transition: TransitionState.Transition,
-    containingContents: Set<ContentKey>,
 ): Boolean {
-    val overscrollContent = transition.currentOverscrollSpec?.content
-    if (overscrollContent != null) {
-        return when (transition) {
-            // If we are overscrolling between scenes, only place/compose the element in the
-            // overscrolling scene.
-            is TransitionState.Transition.ChangeScene -> content == overscrollContent
-
-            // If we are overscrolling an overlay, place/compose the element if [content] is the
-            // overscrolling content or if [content] is the current scene and the overscrolling
-            // overlay does not contain the element.
-            is TransitionState.Transition.ReplaceOverlay,
-            is TransitionState.Transition.ShowOrHideOverlay ->
-                content == overscrollContent ||
-                    (content == transition.currentScene &&
-                        !containingContents.contains(overscrollContent))
-        }
-    }
-
     val scenePicker = elementKey.contentPicker
     val pickedScene =
         scenePicker.contentDuringTransition(
@@ -246,10 +221,14 @@
 
 private fun movableElementState(
     element: MovableElementKey,
-    transitionStates: List<TransitionState>,
+    transitionStates: List<List<TransitionState>>,
 ): TransitionState? {
     val contents = element.contentPicker.contents
-    return elementState(transitionStates, isInContent = { contents.contains(it) })
+    return elementState(
+        transitionStates,
+        elementKey = element,
+        isInContent = { contents.contains(it) },
+    )
 }
 
 private fun movableElementContentWhenIdle(
@@ -270,7 +249,7 @@
     content: ContentKey,
     element: Element,
     elementKey: MovableElementKey,
-    transitionStates: List<TransitionState>,
+    transitionStates: List<List<TransitionState>>,
 ): IntSize {
     // If the content of the movable element was already composed in this scene before, use that
     // target size.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
deleted file mode 100644
index 9622fc1..0000000
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt
+++ /dev/null
@@ -1,178 +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.compose.animation.scene
-
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
-import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode
-import androidx.compose.ui.node.DelegatingNode
-import androidx.compose.ui.node.ModifierNodeElement
-import androidx.compose.ui.platform.InspectorInfo
-
-/**
- * Defines the behavior of the [SceneTransitionLayout] when a scrollable component is scrolled.
- *
- * By default, scrollable elements within the scene have priority during the user's gesture and are
- * not consumed by the [SceneTransitionLayout] unless specifically requested via
- * [nestedScrollToScene].
- */
-enum class NestedScrollBehavior {
-    /**
-     * Overscroll will only be used by the [SceneTransitionLayout] to move to the next scene if the
-     * gesture begins at the edge of the scrollable component (so that a scroll in that direction
-     * can no longer be consumed). If the gesture is partially consumed by the scrollable component,
-     * there will be NO preview of the next scene.
-     *
-     * In addition, during scene transitions, scroll events are consumed by the
-     * [SceneTransitionLayout] instead of the scrollable component.
-     */
-    EdgeNoPreview,
-
-    /**
-     * Overscroll will only be used by the [SceneTransitionLayout] to move to the next scene if the
-     * gesture begins at the edge of the scrollable component. If the gesture is partially consumed
-     * by the scrollable component, there will be a preview of the next scene.
-     *
-     * In addition, during scene transitions, scroll events are consumed by the
-     * [SceneTransitionLayout] instead of the scrollable component.
-     */
-    @Deprecated("This will be removed, see b/378470603") EdgeWithPreview,
-
-    /**
-     * Any overscroll will be used by the [SceneTransitionLayout] to move to the next scene.
-     *
-     * In addition, during scene transitions, scroll events are consumed by the
-     * [SceneTransitionLayout] instead of the scrollable component.
-     */
-    EdgeAlways;
-
-    companion object {
-        val Default = EdgeNoPreview
-    }
-}
-
-internal fun Modifier.nestedScrollToScene(
-    draggableHandler: DraggableHandlerImpl,
-    topOrLeftBehavior: NestedScrollBehavior,
-    bottomOrRightBehavior: NestedScrollBehavior,
-    isExternalOverscrollGesture: () -> Boolean,
-) =
-    this then
-        NestedScrollToSceneElement(
-            draggableHandler = draggableHandler,
-            topOrLeftBehavior = topOrLeftBehavior,
-            bottomOrRightBehavior = bottomOrRightBehavior,
-            isExternalOverscrollGesture = isExternalOverscrollGesture,
-        )
-
-private data class NestedScrollToSceneElement(
-    private val draggableHandler: DraggableHandlerImpl,
-    private val topOrLeftBehavior: NestedScrollBehavior,
-    private val bottomOrRightBehavior: NestedScrollBehavior,
-    private val isExternalOverscrollGesture: () -> Boolean,
-) : ModifierNodeElement<NestedScrollToSceneNode>() {
-    override fun create() =
-        NestedScrollToSceneNode(
-            draggableHandler = draggableHandler,
-            topOrLeftBehavior = topOrLeftBehavior,
-            bottomOrRightBehavior = bottomOrRightBehavior,
-            isExternalOverscrollGesture = isExternalOverscrollGesture,
-        )
-
-    override fun update(node: NestedScrollToSceneNode) {
-        node.update(
-            draggableHandler = draggableHandler,
-            topOrLeftBehavior = topOrLeftBehavior,
-            bottomOrRightBehavior = bottomOrRightBehavior,
-            isExternalOverscrollGesture = isExternalOverscrollGesture,
-        )
-    }
-
-    override fun InspectorInfo.inspectableProperties() {
-        name = "nestedScrollToScene"
-        properties["draggableHandler"] = draggableHandler
-        properties["topOrLeftBehavior"] = topOrLeftBehavior
-        properties["bottomOrRightBehavior"] = bottomOrRightBehavior
-    }
-}
-
-private class NestedScrollToSceneNode(
-    private var draggableHandler: DraggableHandlerImpl,
-    private var topOrLeftBehavior: NestedScrollBehavior,
-    private var bottomOrRightBehavior: NestedScrollBehavior,
-    private var isExternalOverscrollGesture: () -> Boolean,
-) : DelegatingNode() {
-    private var scrollBehaviorOwner: ScrollBehaviorOwner? = null
-
-    private fun findScrollBehaviorOwner(): ScrollBehaviorOwner? {
-        return scrollBehaviorOwner
-            ?: findScrollBehaviorOwner(draggableHandler).also { scrollBehaviorOwner = it }
-    }
-
-    private val updateScrollBehaviorsConnection =
-        object : NestedScrollConnection {
-            /**
-             * When using [NestedScrollConnection.onPostScroll], we can specify the desired behavior
-             * before our parent components. This gives them the option to override our behavior if
-             * they choose.
-             *
-             * The behavior can be communicated at every scroll gesture to ensure that the hierarchy
-             * is respected, even if one of our descendant nodes changes behavior after we set it.
-             */
-            override fun onPostScroll(
-                consumed: Offset,
-                available: Offset,
-                source: NestedScrollSource,
-            ): Offset {
-                // If we have some remaining scroll, that scroll can be used to initiate a
-                // transition between scenes. We can assume that the behavior is only needed if
-                // there is some remaining amount.
-                if (available != Offset.Zero) {
-                    findScrollBehaviorOwner()
-                        ?.updateScrollBehaviors(
-                            topOrLeftBehavior = topOrLeftBehavior,
-                            bottomOrRightBehavior = bottomOrRightBehavior,
-                            isExternalOverscrollGesture = isExternalOverscrollGesture,
-                        )
-                }
-
-                return Offset.Zero
-            }
-        }
-
-    init {
-        delegate(nestedScrollModifierNode(updateScrollBehaviorsConnection, dispatcher = null))
-    }
-
-    override fun onDetach() {
-        scrollBehaviorOwner = null
-    }
-
-    fun update(
-        draggableHandler: DraggableHandlerImpl,
-        topOrLeftBehavior: NestedScrollBehavior,
-        bottomOrRightBehavior: NestedScrollBehavior,
-        isExternalOverscrollGesture: () -> Boolean,
-    ) {
-        this.draggableHandler = draggableHandler
-        this.topOrLeftBehavior = topOrLeftBehavior
-        this.bottomOrRightBehavior = bottomOrRightBehavior
-        this.isExternalOverscrollGesture = isExternalOverscrollGesture
-    }
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index bf7e8e8..7b30a2a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -26,7 +26,6 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.pointer.PointerType
 import androidx.compose.ui.layout.LookaheadScope
 import androidx.compose.ui.platform.LocalDensity
@@ -233,32 +232,6 @@
     )
 
     /**
-     * Adds a [NestedScrollConnection] to intercept scroll events not handled by the scrollable
-     * component.
-     *
-     * @param leftBehavior when we should perform the overscroll animation at the left.
-     * @param rightBehavior when we should perform the overscroll animation at the right.
-     */
-    fun Modifier.horizontalNestedScrollToScene(
-        leftBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
-        rightBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
-        isExternalOverscrollGesture: () -> Boolean = { false },
-    ): Modifier
-
-    /**
-     * Adds a [NestedScrollConnection] to intercept scroll events not handled by the scrollable
-     * component.
-     *
-     * @param topBehavior when we should perform the overscroll animation at the top.
-     * @param bottomBehavior when we should perform the overscroll animation at the bottom.
-     */
-    fun Modifier.verticalNestedScrollToScene(
-        topBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
-        bottomBehavior: NestedScrollBehavior = NestedScrollBehavior.Default,
-        isExternalOverscrollGesture: () -> Boolean = { false },
-    ): Modifier
-
-    /**
      * Don't resize during transitions. This can for instance be used to make sure that scrollable
      * lists keep a constant size during transitions even if its elements are growing/shrinking.
      */
@@ -725,7 +698,7 @@
     transitionInterceptionThreshold: Float = 0f,
     onLayoutImpl: ((SceneTransitionLayoutImpl) -> Unit)? = null,
     sharedElementMap: MutableMap<ElementKey, Element> = remember { mutableMapOf() },
-    ancestorContentKeys: List<ContentKey> = emptyList(),
+    ancestors: List<Ancestor> = remember { emptyList() },
     lookaheadScope: LookaheadScope? = null,
     builder: SceneTransitionLayoutScope.() -> Unit,
 ) {
@@ -742,7 +715,7 @@
                 builder = builder,
                 animationScope = animationScope,
                 elements = sharedElementMap,
-                ancestorContentKeys = ancestorContentKeys,
+                ancestors = ancestors,
                 lookaheadScope = lookaheadScope,
             )
             .also { onLayoutImpl?.invoke(it) }
@@ -765,9 +738,9 @@
                     "when creating it, which is not supported"
             )
         }
-        if (layoutImpl.ancestorContentKeys != ancestorContentKeys) {
+        if (layoutImpl.ancestors != ancestors) {
             error(
-                "This SceneTransitionLayout was bound to a different ancestorContents that was " +
+                "This SceneTransitionLayout was bound to a different ancestors that was " +
                     "used when creating it, which is not supported"
             )
         }
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 d7bac14..e5bdc92 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
@@ -57,6 +57,18 @@
 /** The type for the content of movable elements. */
 internal typealias MovableElementContent = @Composable (@Composable () -> Unit) -> Unit
 
+internal data class Ancestor(
+    val layoutImpl: SceneTransitionLayoutImpl,
+
+    /**
+     * This is the content in which the corresponding descendant of this ancestor appears in.
+     *
+     * Example: When A is the root and has two scenes SA and SB and SB contains a NestedSTL called
+     * B. Then A is the ancestor of B and inContent is SB.
+     */
+    val inContent: ContentKey,
+)
+
 @Stable
 internal class SceneTransitionLayoutImpl(
     internal val state: MutableSceneTransitionLayoutStateImpl,
@@ -83,16 +95,17 @@
     internal val elements: MutableMap<ElementKey, Element> = mutableMapOf(),
 
     /**
-     * When this STL is a [NestedSceneTransitionLayout], this is a list of [ContentKey]s of where
-     * this STL is composed in within its ancestors.
+     * When this STL is a [NestedSceneTransitionLayout], this is a list of [Ancestor]s which
+     * provides a reference to the ancestor STLs and indicates where this STL is composed in within
+     * its ancestors.
      *
      * The root STL holds an emptyList. With each nesting level the parent is supposed to add
      * exactly one scene to the list, therefore the size of this list is equal to the nesting depth
      * of this STL.
      *
-     * This is used to know in which content of the ancestors a sharedElement appears in.
+     * This is used to enable transformations and shared elements across NestedSTLs.
      */
-    internal val ancestorContentKeys: List<ContentKey> = emptyList(),
+    internal val ancestors: List<Ancestor> = emptyList(),
     lookaheadScope: LookaheadScope? = null,
 ) {
 
@@ -558,15 +571,7 @@
                 width = fromSize.width
                 height = fromSize.height
             } else {
-                val overscrollSpec = transition.currentOverscrollSpec
-                val progress =
-                    when {
-                        overscrollSpec == null -> transition.progress
-                        overscrollSpec.content == transition.toScene -> 1f
-                        else -> 0f
-                    }
-
-                val size = lerp(fromSize, toSize, progress)
+                val size = lerp(fromSize, toSize, transition.progress)
                 width = size.width.coerceAtLeast(0)
                 height = size.height.coerceAtLeast(0)
             }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index e8b2b09..568a358 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -382,7 +382,6 @@
         // Compute the [TransformationSpec] when the transition starts.
         val fromContent = transition.fromContent
         val toContent = transition.toContent
-        val orientation = (transition as? TransitionState.DirectionProperties)?.orientation
 
         // Update the transition specs.
         transition.transformationSpec =
@@ -393,14 +392,6 @@
             transitions
                 .transitionSpec(fromContent, toContent, key = transition.key)
                 .previewTransformationSpec(transition)
-        if (orientation != null) {
-            transition.updateOverscrollSpecs(
-                fromSpec = transitions.overscrollSpec(fromContent, orientation),
-                toSpec = transitions.overscrollSpec(toContent, orientation),
-            )
-        } else {
-            transition.updateOverscrollSpecs(fromSpec = null, toSpec = null)
-        }
     }
 
     private fun startTransitionInternal(transition: TransitionState.Transition, chain: Boolean) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index 8df3f2d..756d71c 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -21,7 +21,6 @@
 import androidx.compose.animation.core.SpringSpec
 import androidx.compose.animation.core.snap
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.util.fastForEach
@@ -36,9 +35,7 @@
 internal constructor(
     internal val defaultSwipeSpec: SpringSpec<Float>,
     internal val transitionSpecs: List<TransitionSpecImpl>,
-    internal val overscrollSpecs: List<OverscrollSpecImpl>,
     internal val interruptionHandler: InterruptionHandler,
-    internal val defaultProgressConverter: ProgressConverter,
 ) {
     private val transitionCache =
         mutableMapOf<
@@ -46,9 +43,6 @@
             MutableMap<ContentKey, MutableMap<TransitionKey?, TransitionSpecImpl>>,
         >()
 
-    private val overscrollCache =
-        mutableMapOf<ContentKey, MutableMap<Orientation, OverscrollSpecImpl?>>()
-
     internal fun transitionSpec(
         from: ContentKey,
         to: ContentKey,
@@ -119,28 +113,6 @@
     private fun defaultTransition(from: ContentKey, to: ContentKey) =
         TransitionSpecImpl(key = null, from, to, null, null, TransformationSpec.EmptyProvider)
 
-    internal fun overscrollSpec(scene: ContentKey, orientation: Orientation): OverscrollSpecImpl? =
-        overscrollCache
-            .getOrPut(scene) { mutableMapOf() }
-            .getOrPut(orientation) { overscroll(scene, orientation) { it.content == scene } }
-
-    private fun overscroll(
-        scene: ContentKey,
-        orientation: Orientation,
-        filter: (OverscrollSpecImpl) -> Boolean,
-    ): OverscrollSpecImpl? {
-        var match: OverscrollSpecImpl? = null
-        overscrollSpecs.fastForEach { spec ->
-            if (spec.orientation == orientation && filter(spec)) {
-                if (match != null) {
-                    error("Found multiple overscroll specs for overscroll $scene")
-                }
-                match = spec
-            }
-        }
-        return match
-    }
-
     companion object {
         internal val DefaultSwipeSpec =
             spring(
@@ -153,9 +125,7 @@
             SceneTransitions(
                 defaultSwipeSpec = DefaultSwipeSpec,
                 transitionSpecs = emptyList(),
-                overscrollSpecs = emptyList(),
                 interruptionHandler = DefaultInterruptionHandler,
-                defaultProgressConverter = ProgressConverter.Default,
             )
     }
 }
@@ -286,36 +256,6 @@
     ): TransformationSpecImpl? = previewTransformationSpec?.invoke(transition)
 }
 
-/** The definition of the overscroll behavior of the [content]. */
-internal interface OverscrollSpec {
-    /** The scene we are over scrolling. */
-    val content: ContentKey
-
-    /** The orientation of this [OverscrollSpec]. */
-    val orientation: Orientation
-
-    /** The [TransformationSpec] associated to this [OverscrollSpec]. */
-    val transformationSpec: TransformationSpec
-
-    /**
-     * Function that takes a linear overscroll progress value ranging from 0 to +/- infinity and
-     * outputs the desired **overscroll progress value**.
-     *
-     * When the progress value is:
-     * - 0, the user is not overscrolling.
-     * - 1, the user overscrolled by exactly the [OverscrollBuilder.distance].
-     * - Greater than 1, the user overscrolled more than the [OverscrollBuilder.distance].
-     */
-    val progressConverter: ProgressConverter?
-}
-
-internal class OverscrollSpecImpl(
-    override val content: ContentKey,
-    override val orientation: Orientation,
-    override val transformationSpec: TransformationSpecImpl,
-    override val progressConverter: ProgressConverter?,
-) : OverscrollSpec
-
 /**
  * An implementation of [TransformationSpec] that allows the quick retrieval of an element
  * [ElementTransformations].
@@ -326,19 +266,26 @@
     override val distance: UserActionDistance?,
     override val transformationMatchers: List<TransformationMatcher>,
 ) : TransformationSpec {
-    private val cache = mutableMapOf<ElementKey, MutableMap<ContentKey, ElementTransformations>>()
+    private val cache = mutableMapOf<ElementKey, MutableMap<ContentKey, ElementTransformations?>>()
 
-    internal fun transformations(element: ElementKey, content: ContentKey): ElementTransformations {
+    internal fun transformations(
+        element: ElementKey,
+        content: ContentKey,
+    ): ElementTransformations? {
         return cache
             .getOrPut(element) { mutableMapOf() }
             .getOrPut(content) { computeTransformations(element, content) }
     }
 
+    internal fun hasTransformation(element: ElementKey, content: ContentKey): Boolean {
+        return transformations(element, content) != null
+    }
+
     /** Filter [transformationMatchers] to compute the [ElementTransformations] of [element]. */
     private fun computeTransformations(
         element: ElementKey,
         content: ContentKey,
-    ): ElementTransformations {
+    ): ElementTransformations? {
         var shared: TransformationWithRange<SharedElementTransformation>? = null
         var offset: TransformationWithRange<PropertyTransformation<Offset>>? = null
         var size: TransformationWithRange<PropertyTransformation<IntSize>>? = null
@@ -398,7 +345,13 @@
             }
         }
 
-        return ElementTransformations(shared, offset, size, drawScale, alpha)
+        return if (
+            shared == null && offset == null && size == null && drawScale == null && alpha == null
+        ) {
+            null
+        } else {
+            ElementTransformations(shared, offset, size, drawScale, alpha)
+        }
     }
 
     private fun throwIfNotNull(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SharedElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SharedElement.kt
index 599a152a..ed3a5ca 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SharedElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SharedElement.kt
@@ -30,7 +30,8 @@
     // the transition is running. If the [renderAuthority.size] is 1 it means that that this element
     // is currently composed only in one nesting level, which means that the render authority
     // is determined by "classic" shared element code.
-    return renderAuthority.size == 1 || renderAuthority.first() == content
+    return renderAuthority.size > 0 &&
+        (renderAuthority.size == 1 || renderAuthority.first() == content)
 }
 
 /**
@@ -55,24 +56,6 @@
         return element.shouldBeRenderedBy(content)
     }
 
-    val overscrollContent = transition.currentOverscrollSpec?.content
-    if (overscrollContent != null) {
-        return when (transition) {
-            // If we are overscrolling between scenes, only place/compose the element in the
-            // overscrolling scene.
-            is TransitionState.Transition.ChangeScene -> content == overscrollContent
-
-            // If we are overscrolling an overlay, place/compose the element if [content] is the
-            // overscrolling content or if [content] is the current scene and the overscrolling
-            // overlay does not contain the element.
-            is TransitionState.Transition.ReplaceOverlay,
-            is TransitionState.Transition.ShowOrHideOverlay ->
-                content == overscrollContent ||
-                    (content == transition.currentScene &&
-                        overscrollContent !in element.stateByContent)
-        }
-    }
-
     val scenePicker = elementKey.contentPicker
     val pickedScene =
         scenePicker.contentDuringTransition(
@@ -98,8 +81,9 @@
 ): TransformationWithRange<SharedElementTransformation>? {
     val transformationSpec = transition.transformationSpec
     val sharedInFromContent =
-        transformationSpec.transformations(element, transition.fromContent).shared
-    val sharedInToContent = transformationSpec.transformations(element, transition.toContent).shared
+        transformationSpec.transformations(element, transition.fromContent)?.shared
+    val sharedInToContent =
+        transformationSpec.transformations(element, transition.toContent)?.shared
 
     // The sharedElement() transformation must either be null or be the same in both contents.
     if (sharedInFromContent != sharedInToContent) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
index 5aaeda8..607e4fa 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeAnimation.kt
@@ -25,7 +25,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import com.android.compose.animation.scene.content.state.TransitionState
-import com.android.compose.animation.scene.content.state.TransitionState.DirectionProperties.Companion.DistanceUnspecified
+import com.android.compose.animation.scene.content.state.TransitionState.Companion.DistanceUnspecified
 import kotlin.math.absoluteValue
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.launch
@@ -116,7 +116,6 @@
             val fromScene = layoutState.currentScene
             val toScene = result.toScene
             ChangeSceneSwipeTransition(
-                    layoutState = layoutState,
                     swipeAnimation = swipeAnimation(fromContent = fromScene, toContent = toScene),
                     key = result.transitionKey,
                     replacedTransition = null,
@@ -127,10 +126,9 @@
             val fromScene = layoutState.currentScene
             val overlay = result.overlay
             ShowOrHideOverlaySwipeTransition(
-                    layoutState = layoutState,
-                    fromOrToScene = fromScene,
-                    overlay = overlay,
                     swipeAnimation = swipeAnimation(fromContent = fromScene, toContent = overlay),
+                    overlay = overlay,
+                    fromOrToScene = fromScene,
                     key = result.transitionKey,
                     replacedTransition = null,
                 )
@@ -140,10 +138,9 @@
             val toScene = layoutState.currentScene
             val overlay = result.overlay
             ShowOrHideOverlaySwipeTransition(
-                    layoutState = layoutState,
-                    fromOrToScene = toScene,
-                    overlay = overlay,
                     swipeAnimation = swipeAnimation(fromContent = overlay, toContent = toScene),
+                    overlay = overlay,
+                    fromOrToScene = toScene,
                     key = result.transitionKey,
                     replacedTransition = null,
                 )
@@ -159,7 +156,6 @@
 
             val toOverlay = result.overlay
             ReplaceOverlaySwipeTransition(
-                    layoutState = layoutState,
                     swipeAnimation =
                         swipeAnimation(fromContent = fromOverlay, toContent = toOverlay),
                     key = result.transitionKey,
@@ -170,34 +166,18 @@
     }
 }
 
-internal fun createSwipeAnimation(old: SwipeAnimation<*>): SwipeAnimation<*> {
-    return when (val transition = old.contentTransition) {
-        is TransitionState.Transition.ChangeScene -> {
-            ChangeSceneSwipeTransition(transition as ChangeSceneSwipeTransition).swipeAnimation
-        }
-        is TransitionState.Transition.ShowOrHideOverlay -> {
-            ShowOrHideOverlaySwipeTransition(transition as ShowOrHideOverlaySwipeTransition)
-                .swipeAnimation
-        }
-        is TransitionState.Transition.ReplaceOverlay -> {
-            ReplaceOverlaySwipeTransition(transition as ReplaceOverlaySwipeTransition)
-                .swipeAnimation
-        }
-    }
-}
-
 /** A helper class that contains the main logic for swipe transitions. */
 internal class SwipeAnimation<T : ContentKey>(
     val layoutState: MutableSceneTransitionLayoutStateImpl,
     val fromContent: T,
     val toContent: T,
-    override val orientation: Orientation,
-    override val isUpOrLeft: Boolean,
+    val orientation: Orientation,
+    val isUpOrLeft: Boolean,
     val requiresFullDistanceSwipe: Boolean,
     private val distance: (SwipeAnimation<T>) -> Float,
     currentContent: T = fromContent,
     dragOffset: Float = 0f,
-) : TransitionState.DirectionProperties {
+) {
     /** The [TransitionState.Transition] whose implementation delegates to this [SwipeAnimation]. */
     lateinit var contentTransition: TransitionState.Transition
 
@@ -264,35 +244,16 @@
     val isInPreviewStage: Boolean
         get() = contentTransition.previewTransformationSpec != null && currentContent == fromContent
 
-    override var bouncingContent: ContentKey? = null
-
     /** The current offset caused by the drag gesture. */
     var dragOffset by mutableFloatStateOf(dragOffset)
 
     /** The offset animation that animates the offset once the user lifts their finger. */
     private var offsetAnimation: Animatable<Float, AnimationVector1D>? by mutableStateOf(null)
-    private val offsetAnimationRunnable = CompletableDeferred<(suspend () -> Unit)?>()
+    private val offsetAnimationRunnable = CompletableDeferred<suspend () -> Unit>()
 
     val isUserInputOngoing: Boolean
         get() = offsetAnimation == null
 
-    override val absoluteDistance: Float
-        get() = distance().absoluteValue
-
-    constructor(
-        other: SwipeAnimation<T>
-    ) : this(
-        layoutState = other.layoutState,
-        fromContent = other.fromContent,
-        toContent = other.toContent,
-        orientation = other.orientation,
-        isUpOrLeft = other.isUpOrLeft,
-        requiresFullDistanceSwipe = other.requiresFullDistanceSwipe,
-        distance = other.distance,
-        currentContent = other.currentContent,
-        dragOffset = other.offsetAnimation?.value ?: other.dragOffset,
-    )
-
     suspend fun run() {
         // This animation will first be driven by finger, then when the user lift their finger we
         // start an animation to the target offset (progress = 1f or progress = 0f). We await() for
@@ -333,6 +294,7 @@
         initialVelocity: Float,
         targetContent: T,
         spec: AnimationSpec<Float>? = null,
+        overscrollCompletable: CompletableDeferred<Unit>? = null,
     ): Float {
         check(!isAnimatingOffset()) { "SwipeAnimation.animateOffset() can only be called once" }
 
@@ -391,14 +353,15 @@
         // detail).
         if (skipAnimation) {
             // Unblock the job.
-            offsetAnimationRunnable.complete(null)
+            offsetAnimationRunnable.complete {
+                // Wait for overscroll to finish so that the transition is removed from the STLState
+                // only after the overscroll is done, to avoid dropping frame right when the user
+                // lifts their finger and overscroll is animated to 0.
+                overscrollCompletable?.await()
+            }
             return 0f
         }
 
-        val isTargetGreater = targetOffset > animatable.value
-        val startedWhenOvercrollingTargetContent =
-            if (targetContent == fromContent) initialProgress < 0f else initialProgress > 1f
-
         val swipeSpec =
             spec
                 ?: contentTransition.transformationSpec.swipeSpec
@@ -413,34 +376,13 @@
                     animationSpec = swipeSpec,
                     initialVelocity = initialVelocity,
                 ) {
-                    if (bouncingContent == null) {
-                        val isBouncing =
-                            if (isTargetGreater) {
-                                if (startedWhenOvercrollingTargetContent) {
-                                    value >= targetOffset
-                                } else {
-                                    value > targetOffset
-                                }
-                            } else {
-                                if (startedWhenOvercrollingTargetContent) {
-                                    value <= targetOffset
-                                } else {
-                                    value < targetOffset
-                                }
-                            }
-
-                        if (isBouncing) {
-                            bouncingContent = targetContent
-
-                            // Immediately stop this transition if we are bouncing on a content that
-                            // does not bounce.
-                            if (!contentTransition.isWithinProgressRange(progress)) {
-                                // We are no longer able to consume the velocity, the rest can be
-                                // consumed by another component in the hierarchy.
-                                velocityConsumed.complete(initialVelocity - velocity)
-                                throw SnapException()
-                            }
-                        }
+                    // Immediately stop this transition if we are bouncing on a content that
+                    // does not bounce.
+                    if (!contentTransition.isWithinProgressRange(progress)) {
+                        // We are no longer able to consume the velocity, the rest can be
+                        // consumed by another component in the hierarchy.
+                        velocityConsumed.complete(initialVelocity - velocity)
+                        throw SnapException()
                     }
                 }
             } catch (_: SnapException) {
@@ -450,6 +392,11 @@
                     // The animation consumed the whole available velocity
                     velocityConsumed.complete(initialVelocity)
                 }
+
+                // Wait for overscroll to finish so that the transition is removed from the STLState
+                // only after the overscroll is done, to avoid dropping frame right when the user
+                // lifts their finger and overscroll is animated to 0.
+                overscrollCompletable?.await()
             }
         }
 
@@ -503,7 +450,6 @@
 }
 
 private class ChangeSceneSwipeTransition(
-    val layoutState: MutableSceneTransitionLayoutStateImpl,
     val swipeAnimation: SwipeAnimation<SceneKey>,
     override val key: TransitionKey?,
     replacedTransition: ChangeSceneSwipeTransition?,
@@ -512,17 +458,7 @@
         swipeAnimation.fromContent,
         swipeAnimation.toContent,
         replacedTransition,
-    ),
-    TransitionState.DirectionProperties by swipeAnimation {
-
-    constructor(
-        other: ChangeSceneSwipeTransition
-    ) : this(
-        layoutState = other.layoutState,
-        swipeAnimation = SwipeAnimation(other.swipeAnimation),
-        key = other.key,
-        replacedTransition = other,
-    )
+    ) {
 
     init {
         swipeAnimation.contentTransition = this
@@ -561,7 +497,6 @@
 }
 
 private class ShowOrHideOverlaySwipeTransition(
-    val layoutState: MutableSceneTransitionLayoutStateImpl,
     val swipeAnimation: SwipeAnimation<ContentKey>,
     overlay: OverlayKey,
     fromOrToScene: SceneKey,
@@ -574,18 +509,7 @@
         swipeAnimation.fromContent,
         swipeAnimation.toContent,
         replacedTransition,
-    ),
-    TransitionState.DirectionProperties by swipeAnimation {
-    constructor(
-        other: ShowOrHideOverlaySwipeTransition
-    ) : this(
-        layoutState = other.layoutState,
-        swipeAnimation = SwipeAnimation(other.swipeAnimation),
-        overlay = other.overlay,
-        fromOrToScene = other.fromOrToScene,
-        key = other.key,
-        replacedTransition = other,
-    )
+    ) {
 
     init {
         swipeAnimation.contentTransition = this
@@ -624,7 +548,6 @@
 }
 
 private class ReplaceOverlaySwipeTransition(
-    val layoutState: MutableSceneTransitionLayoutStateImpl,
     val swipeAnimation: SwipeAnimation<OverlayKey>,
     override val key: TransitionKey?,
     replacedTransition: ReplaceOverlaySwipeTransition?,
@@ -633,16 +556,7 @@
         swipeAnimation.fromContent,
         swipeAnimation.toContent,
         replacedTransition,
-    ),
-    TransitionState.DirectionProperties by swipeAnimation {
-    constructor(
-        other: ReplaceOverlaySwipeTransition
-    ) : this(
-        layoutState = other.layoutState,
-        swipeAnimation = SwipeAnimation(other.swipeAnimation),
-        key = other.key,
-        replacedTransition = other,
-    )
+    ) {
 
     init {
         swipeAnimation.contentTransition = this
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 6ef8b86..c5b3df2 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
@@ -23,12 +23,9 @@
 import androidx.compose.ui.input.nestedscroll.nestedScrollModifierNode
 import androidx.compose.ui.input.pointer.PointerEvent
 import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.node.DelegatableNode
 import androidx.compose.ui.node.DelegatingNode
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.PointerInputModifierNode
-import androidx.compose.ui.node.TraversableNode
-import androidx.compose.ui.node.findNearestAncestor
 import androidx.compose.ui.unit.IntSize
 import com.android.compose.animation.scene.content.Content
 
@@ -165,15 +162,11 @@
     private val nestedScrollHandlerImpl =
         NestedScrollHandlerImpl(
             draggableHandler = draggableHandler,
-            topOrLeftBehavior = NestedScrollBehavior.Default,
-            bottomOrRightBehavior = NestedScrollBehavior.Default,
-            isExternalOverscrollGesture = { false },
             pointersInfoOwner = { multiPointerDraggableNode.pointersInfo() },
         )
 
     init {
         delegate(nestedScrollModifierNode(nestedScrollHandlerImpl.connection, dispatcher))
-        delegate(ScrollBehaviorOwnerNode(draggableHandler.nestedScrollKey, nestedScrollHandlerImpl))
     }
 
     private fun onFirstPointerDown() {
@@ -198,40 +191,3 @@
 
     override fun onCancelPointerInput() = multiPointerDraggableNode.onCancelPointerInput()
 }
-
-/** Find the [ScrollBehaviorOwner] for the current orientation. */
-internal fun DelegatableNode.findScrollBehaviorOwner(
-    draggableHandler: DraggableHandlerImpl
-): ScrollBehaviorOwner? {
-    // If there are no scenes in a particular orientation, the corresponding ScrollBehaviorOwnerNode
-    // is removed from the composition.
-    return findNearestAncestor(draggableHandler.nestedScrollKey) as? ScrollBehaviorOwner
-}
-
-internal fun interface ScrollBehaviorOwner {
-    fun updateScrollBehaviors(
-        topOrLeftBehavior: NestedScrollBehavior,
-        bottomOrRightBehavior: NestedScrollBehavior,
-        isExternalOverscrollGesture: () -> Boolean,
-    )
-}
-
-/**
- * We need a node that receives the desired behavior.
- *
- * TODO(b/353234530) move this logic into [SwipeToSceneNode]
- */
-private class ScrollBehaviorOwnerNode(
-    override val traverseKey: Any,
-    val nestedScrollHandlerImpl: NestedScrollHandlerImpl,
-) : Modifier.Node(), TraversableNode, ScrollBehaviorOwner {
-    override fun updateScrollBehaviors(
-        topOrLeftBehavior: NestedScrollBehavior,
-        bottomOrRightBehavior: NestedScrollBehavior,
-        isExternalOverscrollGesture: () -> Boolean,
-    ) {
-        nestedScrollHandlerImpl.topOrLeftBehavior = topOrLeftBehavior
-        nestedScrollHandlerImpl.bottomOrRightBehavior = bottomOrRightBehavior
-        nestedScrollHandlerImpl.isExternalOverscrollGesture = isExternalOverscrollGesture
-    }
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index 952668a..8794df0 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -20,9 +20,7 @@
 import androidx.compose.animation.core.Easing
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.SpringSpec
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import com.android.compose.animation.scene.content.state.TransitionState
@@ -51,12 +49,6 @@
     var interruptionHandler: InterruptionHandler
 
     /**
-     * Default [ProgressConverter] used during overscroll. It lets you change a linear progress into
-     * a function of your choice. Defaults to [ProgressConverter.Default].
-     */
-    var defaultOverscrollProgressConverter: ProgressConverter
-
-    /**
      * Define the default animation to be played when transitioning [to] the specified content, from
      * any content. For the animation specification to apply only when transitioning between two
      * specific contents, use [from] instead.
@@ -103,28 +95,6 @@
         reversePreview: (TransitionBuilder.() -> Unit)? = null,
         builder: TransitionBuilder.() -> Unit = {},
     )
-
-    /**
-     * Define the animation to be played when the [content] is overscrolled in the given
-     * [orientation].
-     *
-     * The overscroll animation always starts from a progress of 0f, and reaches 1f when moving the
-     * [distance] down/right, -1f when moving in the opposite direction.
-     */
-    @Deprecated(
-        "Use verticalOverscrollEffect (or horizontalOverscrollEffect) directly from SceneScope."
-    )
-    fun overscroll(
-        content: ContentKey,
-        orientation: Orientation,
-        builder: OverscrollBuilder.() -> Unit,
-    )
-
-    /**
-     * Prevents overscroll the [content] in the given [orientation], allowing ancestors to
-     * eventually consume the remaining gesture.
-     */
-    fun overscrollDisabled(content: ContentKey, orientation: Orientation)
 }
 
 interface BaseTransitionBuilder : PropertyTransformationBuilder {
@@ -228,35 +198,6 @@
     fun reversed(builder: TransitionBuilder.() -> Unit)
 }
 
-@TransitionDsl
-interface OverscrollBuilder : BaseTransitionBuilder {
-    /**
-     * Function that takes a linear overscroll progress value ranging from 0 to +/- infinity and
-     * outputs the desired **overscroll progress value**.
-     *
-     * When the progress value is:
-     * - 0, the user is not overscrolling.
-     * - 1, the user overscrolled by exactly the [distance].
-     * - Greater than 1, the user overscrolled more than the [distance].
-     */
-    var progressConverter: ProgressConverter?
-
-    /** Translate the element(s) matching [matcher] by ([x], [y]) pixels. */
-    fun translate(
-        matcher: ElementMatcher,
-        x: OverscrollScope.() -> Float = { 0f },
-        y: OverscrollScope.() -> Float = { 0f },
-    )
-}
-
-interface OverscrollScope : Density {
-    /**
-     * Return the absolute distance between fromScene and toScene, if available, otherwise
-     * [DistanceUnspecified].
-     */
-    val absoluteDistance: Float
-}
-
 /**
  * An interface to decide where we should draw shared Elements or compose MovableElements.
  *
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
index 6742b32..a164996 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
@@ -22,9 +22,7 @@
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.SpringSpec
 import androidx.compose.animation.core.VectorConverter
-import androidx.compose.animation.core.snap
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.unit.Dp
 import com.android.compose.animation.scene.content.state.TransitionState
@@ -33,7 +31,6 @@
 import com.android.compose.animation.scene.transformation.DrawScale
 import com.android.compose.animation.scene.transformation.EdgeTranslate
 import com.android.compose.animation.scene.transformation.Fade
-import com.android.compose.animation.scene.transformation.OverscrollTranslate
 import com.android.compose.animation.scene.transformation.ScaleSize
 import com.android.compose.animation.scene.transformation.SharedElementTransformation
 import com.android.compose.animation.scene.transformation.Transformation
@@ -43,22 +40,14 @@
 
 internal fun transitionsImpl(builder: SceneTransitionsBuilder.() -> Unit): SceneTransitions {
     val impl = SceneTransitionsBuilderImpl().apply(builder)
-    return SceneTransitions(
-        impl.defaultSwipeSpec,
-        impl.transitionSpecs,
-        impl.transitionOverscrollSpecs,
-        impl.interruptionHandler,
-        impl.defaultOverscrollProgressConverter,
-    )
+    return SceneTransitions(impl.defaultSwipeSpec, impl.transitionSpecs, impl.interruptionHandler)
 }
 
 private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
     override var defaultSwipeSpec: SpringSpec<Float> = SceneTransitions.DefaultSwipeSpec
     override var interruptionHandler: InterruptionHandler = DefaultInterruptionHandler
-    override var defaultOverscrollProgressConverter: ProgressConverter = ProgressConverter.Default
 
     val transitionSpecs = mutableListOf<TransitionSpecImpl>()
-    val transitionOverscrollSpecs = mutableListOf<OverscrollSpecImpl>()
 
     override fun to(
         to: ContentKey,
@@ -81,45 +70,6 @@
         transition(from = from, to = to, key = key, preview, reversePreview, builder)
     }
 
-    override fun overscroll(
-        content: ContentKey,
-        orientation: Orientation,
-        builder: OverscrollBuilder.() -> Unit,
-    ) {
-        val impl = OverscrollBuilderImpl().apply(builder)
-        check(impl.transformationMatchers.isNotEmpty()) {
-            "This method does not allow empty transformations. " +
-                "Use overscrollDisabled($content, $orientation) instead."
-        }
-        overscrollSpec(content, orientation, impl)
-    }
-
-    override fun overscrollDisabled(content: ContentKey, orientation: Orientation) {
-        overscrollSpec(content, orientation, OverscrollBuilderImpl())
-    }
-
-    private fun overscrollSpec(
-        content: ContentKey,
-        orientation: Orientation,
-        impl: OverscrollBuilderImpl,
-    ): OverscrollSpec {
-        val spec =
-            OverscrollSpecImpl(
-                content = content,
-                orientation = orientation,
-                transformationSpec =
-                    TransformationSpecImpl(
-                        progressSpec = snap(),
-                        swipeSpec = null,
-                        distance = impl.distance,
-                        transformationMatchers = impl.transformationMatchers,
-                    ),
-                progressConverter = impl.progressConverter,
-            )
-        transitionOverscrollSpecs.add(spec)
-        return spec
-    }
-
     private fun transition(
         from: ContentKey?,
         to: ContentKey?,
@@ -295,15 +245,3 @@
         fractionRange(start, end, easing, builder)
     }
 }
-
-internal open class OverscrollBuilderImpl : BaseTransitionBuilderImpl(), OverscrollBuilder {
-    override var progressConverter: ProgressConverter? = null
-
-    override fun translate(
-        matcher: ElementMatcher,
-        x: OverscrollScope.() -> Float,
-        y: OverscrollScope.() -> Float,
-    ) {
-        addTransformation(matcher, OverscrollTranslate.Factory(x, y))
-    }
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 152f05e..8c5a727 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -31,6 +31,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.zIndex
+import com.android.compose.animation.scene.Ancestor
 import com.android.compose.animation.scene.AnimatedState
 import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.ContentScope
@@ -42,7 +43,6 @@
 import com.android.compose.animation.scene.MovableElement
 import com.android.compose.animation.scene.MovableElementContentScope
 import com.android.compose.animation.scene.MovableElementKey
-import com.android.compose.animation.scene.NestedScrollBehavior
 import com.android.compose.animation.scene.SceneTransitionLayoutForTesting
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
 import com.android.compose.animation.scene.SceneTransitionLayoutScope
@@ -57,7 +57,6 @@
 import com.android.compose.animation.scene.effect.VisualEffect
 import com.android.compose.animation.scene.element
 import com.android.compose.animation.scene.modifiers.noResizeDuringTransitions
-import com.android.compose.animation.scene.nestedScrollToScene
 import com.android.compose.modifiers.thenIf
 import com.android.compose.ui.graphics.ContainerState
 import com.android.compose.ui.graphics.container
@@ -173,32 +172,6 @@
         )
     }
 
-    override fun Modifier.horizontalNestedScrollToScene(
-        leftBehavior: NestedScrollBehavior,
-        rightBehavior: NestedScrollBehavior,
-        isExternalOverscrollGesture: () -> Boolean,
-    ): Modifier {
-        return nestedScrollToScene(
-            draggableHandler = layoutImpl.horizontalDraggableHandler,
-            topOrLeftBehavior = leftBehavior,
-            bottomOrRightBehavior = rightBehavior,
-            isExternalOverscrollGesture = isExternalOverscrollGesture,
-        )
-    }
-
-    override fun Modifier.verticalNestedScrollToScene(
-        topBehavior: NestedScrollBehavior,
-        bottomBehavior: NestedScrollBehavior,
-        isExternalOverscrollGesture: () -> Boolean,
-    ): Modifier {
-        return nestedScrollToScene(
-            draggableHandler = layoutImpl.verticalDraggableHandler,
-            topOrLeftBehavior = topBehavior,
-            bottomOrRightBehavior = bottomBehavior,
-            isExternalOverscrollGesture = isExternalOverscrollGesture,
-        )
-    }
-
     override fun Modifier.noResizeDuringTransitions(): Modifier {
         return noResizeDuringTransitions(layoutState = layoutImpl.state)
     }
@@ -209,16 +182,17 @@
         modifier: Modifier,
         builder: SceneTransitionLayoutScope.() -> Unit,
     ) {
+        val ancestors =
+            remember(layoutImpl, contentKey, layoutImpl.ancestors) {
+                layoutImpl.ancestors + Ancestor(layoutImpl, contentKey)
+            }
         SceneTransitionLayoutForTesting(
             state,
             modifier,
             onLayoutImpl = null,
             builder = builder,
             sharedElementMap = layoutImpl.elements,
-            ancestorContentKeys =
-                remember(layoutImpl.ancestorContentKeys, contentKey) {
-                    layoutImpl.ancestorContentKeys + contentKey
-                },
+            ancestors = ancestors,
             lookaheadScope = layoutImpl.lookaheadScope,
         )
     }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
index 29be445..e7ca511 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -20,15 +20,12 @@
 import androidx.compose.animation.core.AnimationVector1D
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.runtime.Stable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
 import com.android.compose.animation.scene.OverlayKey
-import com.android.compose.animation.scene.OverscrollSpecImpl
 import com.android.compose.animation.scene.ProgressVisibilityThreshold
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
@@ -254,40 +251,13 @@
         internal open val isInPreviewStage: Boolean = false
 
         /**
-         * The current [TransformationSpecImpl] and [OverscrollSpecImpl] associated to this
-         * transition.
+         * The current [TransformationSpecImpl] associated to this transition.
          *
          * Important: These will be set exactly once, when this transition is
          * [started][MutableSceneTransitionLayoutStateImpl.startTransition].
          */
         internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
         internal var previewTransformationSpec: TransformationSpecImpl? = null
-        private var fromOverscrollSpec: OverscrollSpecImpl? = null
-        private var toOverscrollSpec: OverscrollSpecImpl? = null
-
-        /**
-         * The current [OverscrollSpecImpl], if this transition is currently overscrolling.
-         *
-         * Note: This is backed by a State<OverscrollSpecImpl?> because the overscroll spec is
-         * derived from progress, and we don't want readers of currentOverscrollSpec to recompose
-         * every time progress is changed.
-         */
-        private val _currentOverscrollSpec: State<OverscrollSpecImpl?>? =
-            if (this !is DirectionProperties) {
-                null
-            } else {
-                derivedStateOf {
-                    val progress = progress
-                    val bouncingContent = bouncingContent
-                    when {
-                        progress < 0f || bouncingContent == fromContent -> fromOverscrollSpec
-                        progress > 1f || bouncingContent == toContent -> toOverscrollSpec
-                        else -> null
-                    }
-                }
-            }
-        internal val currentOverscrollSpec: OverscrollSpecImpl?
-            get() = _currentOverscrollSpec?.value
 
         /**
          * An animatable that animates from 1f to 0f. This will be used to nicely animate the sudden
@@ -395,27 +365,13 @@
             }
         }
 
-        internal fun updateOverscrollSpecs(
-            fromSpec: OverscrollSpecImpl?,
-            toSpec: OverscrollSpecImpl?,
-        ) {
-            fromOverscrollSpec = fromSpec
-            toOverscrollSpec = toSpec
-        }
-
-        /** Returns if the [progress] value of this transition can go beyond range `[0; 1]` */
+        /**
+         * Checks if the given [progress] value is within the valid range for this transition.
+         *
+         * The valid range is between 0f and 1f, inclusive.
+         */
         internal fun isWithinProgressRange(progress: Float): Boolean {
-            // If the properties are missing we assume that every [Transition] can overscroll
-            if (this !is DirectionProperties) return true
-            // [OverscrollSpec] for the current scene, even if it hasn't started overscrolling yet.
-            val specForCurrentScene =
-                when {
-                    progress <= 0f -> fromOverscrollSpec
-                    progress >= 1f -> toOverscrollSpec
-                    else -> null
-                } ?: return true
-
-            return specForCurrentScene.transformationSpec.transformationMatchers.isNotEmpty()
+            return progress >= 0f && progress <= 1f
         }
 
         internal open fun interruptionProgress(layoutImpl: SceneTransitionLayoutImpl): Float {
@@ -444,36 +400,7 @@
         }
     }
 
-    interface DirectionProperties {
-        /**
-         * The position of the [Transition.toContent].
-         *
-         * Used to understand the direction of the overscroll.
-         */
-        val isUpOrLeft: Boolean
-
-        /**
-         * The relative orientation between [Transition.fromContent] and [Transition.toContent].
-         *
-         * Used to understand the orientation of the overscroll.
-         */
-        val orientation: Orientation
-
-        /**
-         * Return the absolute distance between fromScene and toScene, if available, otherwise
-         * [DistanceUnspecified].
-         */
-        val absoluteDistance: Float
-
-        /**
-         * The content (scene or overlay) around which the transition is currently bouncing. When
-         * not `null`, this transition is currently oscillating around this content and will soon
-         * settle to that content.
-         */
-        val bouncingContent: ContentKey?
-
-        companion object {
-            const val DistanceUnspecified = 0f
-        }
+    companion object {
+        const val DistanceUnspecified = 0f
     }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt
index 944bd85..7c4dbf1 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/reveal/ContainerReveal.kt
@@ -156,12 +156,7 @@
         // implement HasOverscrollProperties if the transition is triggered and not gesture based.
         val idleSize = checkNotNull(element.targetSize(content))
         val userActionDistance = idleSize.height
-        val progress =
-            when ((transition as? TransitionState.DirectionProperties)?.bouncingContent) {
-                null -> transition.progressTo(content)
-                content -> 1f
-                else -> 0f
-            }
+        val progress = transition.progressTo(content)
         val distance = (progress * userActionDistance).fastCoerceAtLeast(0f)
         val threshold = distanceThreshold.toPx()
 
@@ -256,19 +251,7 @@
 
     private fun targetAlpha(transition: TransitionState.Transition, content: ContentKey): Float {
         if (transition.isUserInputOngoing) {
-            if (transition !is TransitionState.DirectionProperties) {
-                error(
-                    "Unsupported transition driven by user input but that does not have " +
-                        "overscroll properties: $transition"
-                )
-            }
-
-            val bouncingContent = transition.bouncingContent
-            return if (bouncingContent != null) {
-                if (bouncingContent == content) 1f else 0f
-            } else {
-                if (transition.progressTo(content) > 0f) 1f else 0f
-            }
+            return if (transition.progressTo(content) > 0f) 1f else 0f
         }
 
         // The transition was committed (the user released their finger), so the alpha depends on
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
index 432add3..30d2de6 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
@@ -17,11 +17,9 @@
 package com.android.compose.animation.scene.transformation
 
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.ElementKey
-import com.android.compose.animation.scene.OverscrollScope
 import com.android.compose.animation.scene.content.state.TransitionState
 
 internal class Translate private constructor(private val x: Dp, private val y: Dp) :
@@ -41,71 +39,3 @@
         override fun create(): Transformation = Translate(x, y)
     }
 }
-
-internal class OverscrollTranslate
-private constructor(
-    private val x: OverscrollScope.() -> Float,
-    private val y: OverscrollScope.() -> Float,
-) : InterpolatedPropertyTransformation<Offset> {
-    override val property = PropertyTransformation.Property.Offset
-
-    private val cachedOverscrollScope = CachedOverscrollScope()
-
-    override fun PropertyTransformationScope.transform(
-        content: ContentKey,
-        element: ElementKey,
-        transition: TransitionState.Transition,
-        value: Offset,
-    ): Offset {
-        // As this object is created by OverscrollBuilderImpl and we retrieve the current
-        // OverscrollSpec only when the transition implements HasOverscrollProperties, we can assume
-        // that this method was invoked after performing this check.
-        val overscrollProperties = transition as TransitionState.DirectionProperties
-        val overscrollScope =
-            cachedOverscrollScope.getFromCacheOrCompute(density = this, overscrollProperties)
-
-        return Offset(x = value.x + overscrollScope.x(), y = value.y + overscrollScope.y())
-    }
-
-    class Factory(
-        private val x: OverscrollScope.() -> Float,
-        private val y: OverscrollScope.() -> Float,
-    ) : Transformation.Factory {
-        override fun create(): Transformation = OverscrollTranslate(x, y)
-    }
-}
-
-/**
- * A helper class to cache a [OverscrollScope] given a [Density] and
- * [TransitionState.DirectionProperties]. This helps avoid recreating a scope every frame whenever
- * an overscroll transition is computed.
- */
-private class CachedOverscrollScope {
-    private var previousScope: OverscrollScope? = null
-    private var previousDensity: Density? = null
-    private var previousOverscrollProperties: TransitionState.DirectionProperties? = null
-
-    fun getFromCacheOrCompute(
-        density: Density,
-        overscrollProperties: TransitionState.DirectionProperties,
-    ): OverscrollScope {
-        if (
-            previousScope == null ||
-                density != previousDensity ||
-                previousOverscrollProperties != overscrollProperties
-        ) {
-            val scope =
-                object : OverscrollScope, Density by density {
-                    override val absoluteDistance: Float
-                        get() = overscrollProperties.absoluteDistance
-                }
-
-            previousScope = scope
-            previousDensity = density
-            previousOverscrollProperties = overscrollProperties
-            return scope
-        }
-
-        return checkNotNull(previousScope)
-    }
-}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
index 2fd1d8d8..62ec221 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
@@ -19,15 +19,12 @@
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.background
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
 import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -447,59 +444,6 @@
     }
 
     @Test
-    fun animatedValueDoesNotOverscrollWhenOverscrollIsSpecified() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions { overscrollDisabled(SceneB, Orientation.Horizontal) },
-                )
-            }
-
-        val key = ValueKey("foo")
-        val lastValues = mutableMapOf<ContentKey, Float>()
-
-        @Composable
-        fun ContentScope.animateFloat(value: Float, key: ValueKey) {
-            val animatedValue = animateContentFloatAsState(value, key)
-            LaunchedEffect(animatedValue) {
-                snapshotFlow { animatedValue.value }.collect { lastValues[contentKey] = it }
-            }
-        }
-
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayout(state) {
-                    scene(SceneA) { animateFloat(0f, key) }
-                    scene(SceneB) { animateFloat(100f, key) }
-                }
-            }
-
-        // Overscroll on A at -100%: value should be interpolated given that there is no overscroll
-        // defined for scene A.
-        var progress by mutableStateOf(-1f)
-        scope.launch {
-            state.startTransition(transition(from = SceneA, to = SceneB, progress = { progress }))
-        }
-        rule.waitForIdle()
-        assertThat(lastValues[SceneA]).isWithin(0.001f).of(-100f)
-        assertThat(lastValues[SceneB]).isWithin(0.001f).of(-100f)
-
-        // Middle of the transition.
-        progress = 0.5f
-        rule.waitForIdle()
-        assertThat(lastValues[SceneA]).isWithin(0.001f).of(50f)
-        assertThat(lastValues[SceneB]).isWithin(0.001f).of(50f)
-
-        // Overscroll on B at 200%: value should not be interpolated given that there is an
-        // overscroll defined for scene B.
-        progress = 2f
-        rule.waitForIdle()
-        assertThat(lastValues[SceneA]).isWithin(0.001f).of(100f)
-        assertThat(lastValues[SceneB]).isWithin(0.001f).of(100f)
-    }
-
-    @Test
     fun interpolatedColor() {
         val a = Color.Red
         val b = Color.Green
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 6985644..5a35d11 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -18,7 +18,6 @@
 
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.overscroll
 import androidx.compose.material3.Text
 import androidx.compose.ui.Modifier
@@ -31,9 +30,6 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.Velocity
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compose.animation.scene.NestedScrollBehavior.EdgeAlways
-import com.android.compose.animation.scene.NestedScrollBehavior.EdgeNoPreview
-import com.android.compose.animation.scene.NestedScrollBehavior.EdgeWithPreview
 import com.android.compose.animation.scene.TestOverlays.OverlayA
 import com.android.compose.animation.scene.TestOverlays.OverlayB
 import com.android.compose.animation.scene.TestScenes.SceneA
@@ -141,15 +137,9 @@
 
         var pointerInfoOwner: () -> PointersInfo = { pointersDown() }
 
-        fun nestedScrollConnection(
-            nestedScrollBehavior: NestedScrollBehavior,
-            isExternalOverscrollGesture: Boolean = false,
-        ) =
+        fun nestedScrollConnection() =
             NestedScrollHandlerImpl(
                     draggableHandler = draggableHandler,
-                    topOrLeftBehavior = nestedScrollBehavior,
-                    bottomOrRightBehavior = nestedScrollBehavior,
-                    isExternalOverscrollGesture = { isExternalOverscrollGesture },
                     pointersInfoOwner = { pointerInfoOwner() },
                 )
                 .connection
@@ -270,13 +260,12 @@
             velocity: Float,
             canChangeScene: Boolean = true,
             onAnimationStart: () -> Unit,
-            expectedConsumedVelocity: Float,
         ) =
             onDragStoppedAnimateNow(
                 velocity = velocity,
                 canChangeScene = canChangeScene,
                 onAnimationStart = onAnimationStart,
-                onAnimationEnd = { assertThat(it).isEqualTo(expectedConsumedVelocity) },
+                onAnimationEnd = {},
             )
 
         fun DragController.onDragStoppedAnimateLater(
@@ -358,7 +347,6 @@
         dragController.onDragStoppedAnimateNow(
             velocity = velocityThreshold - 0.01f,
             onAnimationStart = { assertTransition(currentScene = SceneA) },
-            expectedConsumedVelocity = velocityThreshold - 0.01f,
         )
 
         assertIdle(currentScene = SceneA)
@@ -386,7 +374,6 @@
                         progress = 0f,
                     )
                 },
-                expectedConsumedVelocity = velocityThreshold - 0.01f,
             )
 
             assertIdle(currentScene = SceneA)
@@ -400,7 +387,6 @@
         dragController.onDragStoppedAnimateNow(
             velocity = velocityThreshold,
             onAnimationStart = { assertTransition(currentScene = SceneC) },
-            expectedConsumedVelocity = velocityThreshold,
         )
         assertIdle(currentScene = SceneC)
     }
@@ -413,7 +399,6 @@
         dragController.onDragStoppedAnimateNow(
             velocity = 0f,
             onAnimationStart = { assertTransition(currentScene = SceneA) },
-            expectedConsumedVelocity = 0f,
         )
         assertIdle(currentScene = SceneA)
     }
@@ -462,13 +447,11 @@
         )
 
         // Reverse drag direction, it does not replace the previous transition.
-        dragController.onDragDelta(pixels = down(fractionOfScreen = 0.5f))
-        assertTransition(
-            currentScene = SceneA,
-            fromScene = SceneA,
-            toScene = SceneB,
-            progress = -0.3f,
+        dragController.onDragDelta(
+            pixels = down(fractionOfScreen = 0.5f),
+            expectedConsumed = down(0.2f),
         )
+        assertTransition(currentScene = SceneA, fromScene = SceneA, toScene = SceneB, progress = 0f)
     }
 
     @Test
@@ -515,7 +498,6 @@
             onAnimationStart = {
                 assertTransition(currentScene = SceneC, fromScene = SceneA, toScene = SceneC)
             },
-            expectedConsumedVelocity = 0f,
         )
         assertIdle(currentScene = SceneC)
     }
@@ -535,7 +517,6 @@
             onAnimationStart = {
                 assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.2f)
             },
-            expectedConsumedVelocity = down(fractionOfScreen = 0.1f),
         )
         assertIdle(SceneA)
 
@@ -575,293 +556,6 @@
     }
 
     @Test
-    fun onInitialPreScroll_EdgeWithOverscroll_doNotChangeState() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        nestedScroll.onPreScroll(
-            available = downOffset(fractionOfScreen = 0.1f),
-            source = UserInput,
-        )
-        assertIdle(currentScene = SceneA)
-    }
-
-    @Test
-    fun onPostScrollWithNothingAvailable_EdgeWithOverscroll_doNotChangeState() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        val consumed =
-            nestedScroll.onPostScroll(
-                consumed = Offset.Zero,
-                available = Offset.Zero,
-                source = UserInput,
-            )
-
-        assertIdle(currentScene = SceneA)
-        assertThat(consumed).isEqualTo(Offset.Zero)
-    }
-
-    @Test
-    fun onPostScrollWithSomethingAvailable_startSceneTransition() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        val consumed =
-            nestedScroll.onPostScroll(
-                consumed = Offset.Zero,
-                available = downOffset(fractionOfScreen = 0.1f),
-                source = UserInput,
-            )
-
-        assertTransition(currentScene = SceneA)
-        assertThat(progress).isEqualTo(0.1f)
-        assertThat(consumed).isEqualTo(downOffset(fractionOfScreen = 0.1f))
-    }
-
-    @Test
-    fun afterSceneTransitionIsStarted_interceptPreScrollEvents() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        assertTransition(currentScene = SceneA)
-
-        assertThat(progress).isEqualTo(0.1f)
-
-        // start intercept preScroll
-        val consumed =
-            nestedScroll.onPreScroll(
-                available = downOffset(fractionOfScreen = 0.1f),
-                source = UserInput,
-            )
-        assertThat(progress).isEqualTo(0.2f)
-
-        // do nothing on postScroll
-        nestedScroll.onPostScroll(consumed = consumed, available = Offset.Zero, source = UserInput)
-        assertThat(progress).isEqualTo(0.2f)
-
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        assertThat(progress).isEqualTo(0.3f)
-        assertTransition(currentScene = SceneA)
-    }
-
-    private fun TestGestureScope.preScrollAfterSceneTransition(
-        firstScroll: Float,
-        secondScroll: Float,
-    ) {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        // start scene transition
-        nestedScroll.scroll(available = Offset(0f, firstScroll))
-
-        // stop scene transition (start the "stop animation")
-        nestedScroll.preFling(available = Velocity.Zero)
-
-        // a pre scroll event, that could be intercepted by DraggableHandlerImpl
-        nestedScroll.onPreScroll(available = Offset(0f, secondScroll), source = UserInput)
-    }
-
-    @Test
-    fun scrollAndFling_scrollMoreThanInterceptable_goToIdleOnNextScene() = runGestureTest {
-        val firstScroll = -(1f - transitionInterceptionThreshold + 0.0001f) * SCREEN_SIZE
-        val secondScroll = -0.01f
-
-        preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
-        advanceUntilIdle()
-        assertIdle(SceneB)
-    }
-
-    @Test
-    fun duringATransition_aNewScrollGesture_shouldTakeControl() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        // First gesture
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        assertTransition(currentScene = SceneA)
-        nestedScroll.preFling(available = Velocity.Zero)
-        assertTransition(currentScene = SceneA)
-
-        // Second gesture, it starts during onStop() animation
-        nestedScroll.scroll(downOffset(0.1f))
-        assertTransition(currentScene = SceneA)
-
-        // Allows onStop() to complete or cancel
-        advanceUntilIdle()
-
-        // Second gesture continues
-        nestedScroll.scroll(downOffset(0.1f))
-        assertTransition(currentScene = SceneA)
-
-        // Second gesture ends
-        nestedScroll.preFling(available = Velocity.Zero)
-        assertTransition(currentScene = SceneA)
-
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneA)
-    }
-
-    @Test
-    fun onPreFling_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        assertTransition(currentScene = SceneA)
-
-        nestedScroll.preFling(available = Velocity.Zero)
-        assertTransition(currentScene = SceneA)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneA)
-    }
-
-    private fun TestGestureScope.flingAfterScroll(
-        use: NestedScrollBehavior,
-        idleAfterScroll: Boolean,
-    ) {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = use)
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        if (idleAfterScroll) assertIdle(SceneA) else assertTransition(SceneA)
-
-        nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
-    }
-
-    @Test
-    fun flingAfterScroll_EdgeNoOverscroll_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = EdgeNoPreview, idleAfterScroll = false)
-
-        assertTransition(currentScene = SceneC)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneC)
-    }
-
-    @Test
-    fun flingAfterScroll_EdgeWithOverscroll_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = EdgeWithPreview, idleAfterScroll = false)
-
-        assertTransition(currentScene = SceneC)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneC)
-    }
-
-    @Test
-    fun flingAfterScroll_Always_goToNextScene() = runGestureTest {
-        flingAfterScroll(use = EdgeAlways, idleAfterScroll = false)
-
-        assertTransition(currentScene = SceneC)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneC)
-    }
-
-    /** we started the scroll in the scene, then fling with the velocityThreshold */
-    private fun TestGestureScope.flingAfterScrollStartedInScene(
-        use: NestedScrollBehavior,
-        idleAfterScroll: Boolean,
-    ) {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = use)
-        // scroll consumed in child
-        nestedScroll.scroll(
-            available = downOffset(fractionOfScreen = 0.1f),
-            consumedByScroll = downOffset(fractionOfScreen = 0.1f),
-        )
-
-        // scroll offsetY10 is all available for parents
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        if (idleAfterScroll) assertIdle(SceneA) else assertTransition(SceneA)
-
-        nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
-    }
-
-    @Test
-    fun flingAfterScrollStartedInScene_EdgeNoOverscroll_doNothing() = runGestureTest {
-        flingAfterScrollStartedInScene(use = EdgeNoPreview, idleAfterScroll = true)
-
-        assertIdle(currentScene = SceneA)
-    }
-
-    @Test
-    fun flingAfterScrollStartedInScene_EdgeWithOverscroll_doOverscrollAnimation() = runGestureTest {
-        flingAfterScrollStartedInScene(use = EdgeWithPreview, idleAfterScroll = false)
-
-        assertTransition(currentScene = SceneA)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneA)
-    }
-
-    @Test
-    fun flingAfterScrollStartedInScene_Always_goToNextScene() = runGestureTest {
-        flingAfterScrollStartedInScene(use = EdgeAlways, idleAfterScroll = false)
-
-        assertTransition(currentScene = SceneC)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneC)
-    }
-
-    @Test
-    fun flingAfterScrollStartedByExternalOverscrollGesture() = runGestureTest {
-        val nestedScroll =
-            nestedScrollConnection(
-                nestedScrollBehavior = EdgeWithPreview,
-                isExternalOverscrollGesture = true,
-            )
-
-        // scroll not consumed in child
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-
-        // scroll offsetY10 is all available for parents
-        nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
-        assertTransition(SceneA)
-
-        nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
-    }
-
-    @Test
-    fun beforeNestedScrollStart_stop_shouldBeIgnored() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
-        nestedScroll.preFling(available = Velocity(0f, velocityThreshold))
-        assertIdle(currentScene = SceneA)
-    }
-
-    @Test
-    fun startNestedScrollWhileDragging() = runGestureTest {
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
-
-        val offsetY10 = downOffset(fractionOfScreen = 0.1f)
-
-        // Start a drag and then stop it, given that
-        val dragController = onDragStarted(overSlop = up(0.1f))
-
-        assertTransition(currentScene = SceneA)
-        assertThat(progress).isEqualTo(0.1f)
-
-        // now we can intercept the scroll events
-        nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.1f)
-
-        // this should be ignored, we are scrolling now!
-        dragController.onDragStoppedAnimateNow(
-            velocity = -velocityThreshold,
-            onAnimationStart = { assertTransition(currentScene = SceneA) },
-            expectedConsumedVelocity = 0f,
-        )
-        assertTransition(currentScene = SceneA)
-
-        nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.2f)
-
-        nestedScroll.scroll(available = -offsetY10)
-        assertThat(progress).isEqualTo(0.3f)
-
-        nestedScroll.preFling(available = Velocity(0f, -velocityThreshold))
-        assertTransition(currentScene = SceneB)
-
-        // wait for the stop animation
-        advanceUntilIdle()
-        assertIdle(currentScene = SceneB)
-    }
-
-    @Test
     fun freezeAndAnimateToCurrentState() = runGestureTest {
         // Start at scene C.
         navigateToSceneC()
@@ -893,7 +587,6 @@
         dragController.onDragStoppedAnimateNow(
             velocity = -velocityThreshold,
             onAnimationStart = { assertTransition(fromScene = SceneA, toScene = SceneB) },
-            expectedConsumedVelocity = -velocityThreshold,
         )
         assertIdle(SceneA)
     }
@@ -901,7 +594,6 @@
     @Test
     fun blockTransition_animated() = runGestureTest {
         assertIdle(SceneA)
-        layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
 
         // Swipe up to scene B. Overscroll 50%.
         val dragController = onDragStarted(overSlop = up(1.5f), expectedConsumedOverSlop = up(1.0f))
@@ -916,7 +608,7 @@
         assertTransition(currentScene = SceneA, fromScene = SceneA, toScene = SceneB, progress = 1f)
 
         val consumed = velocityConsumed.await()
-        assertThat(consumed).isEqualTo(-velocityThreshold)
+        assertThat(consumed).isNotEqualTo(0f)
         assertIdle(SceneA)
     }
 
@@ -924,7 +616,7 @@
     fun nestedScrollUseFromSourceInfo() = runGestureTest {
         // Start at scene C.
         navigateToSceneC()
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
+        val nestedScroll = nestedScrollConnection()
 
         // Drag from the **top** of the screen
         pointerInfoOwner = { pointersDown() }
@@ -961,7 +653,7 @@
     fun ignoreMouseWheel() = runGestureTest {
         // Start at scene C.
         navigateToSceneC()
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
+        val nestedScroll = nestedScrollConnection()
 
         // Use mouse wheel
         pointerInfoOwner = { PointersInfo.MouseWheel }
@@ -983,40 +675,7 @@
     }
 
     @Test
-    fun emptyOverscrollImmediatelyAbortsSettleAnimationWhenOverProgress() = runGestureTest {
-        // Overscrolling on scene B does nothing.
-        layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
-
-        // Swipe up to scene B at progress = 200%.
-        val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
-        val dragController =
-            onDragStarted(
-                pointersInfo = middle,
-                overSlop = up(2f),
-                // Overscroll is disabled, it will scroll up to 100%
-                expectedConsumedOverSlop = up(1f),
-            )
-
-        // The progress value is coerced in `[0..1]`
-        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
-
-        // Release the finger.
-        dragController.onDragStoppedAnimateNow(
-            velocity = -velocityThreshold,
-            onAnimationStart = {
-                // Given that we are at progress >= 100% and that the overscroll on scene B is doing
-                // nothing, we are already idle.
-                assertIdle(SceneB)
-            },
-            expectedConsumedVelocity = 0f,
-        )
-    }
-
-    @Test
     fun emptyOverscrollAbortsSettleAnimationAndExposeTheConsumedVelocity() = runGestureTest {
-        // Overscrolling on scene B does nothing.
-        layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
-
         // Swipe up to scene B at progress = 200%.
         val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
         val dragController = onDragStarted(pointersInfo = middle, overSlop = up(0.99f))
@@ -1027,7 +686,7 @@
             velocity = -velocityThreshold,
             onAnimationStart = { assertTransition(fromScene = SceneA, toScene = SceneB) },
             onAnimationEnd = { consumedVelocity ->
-                // Our progress value was 0.99f and it is coerced in `[0..1]` (overscrollDisabled).
+                // Our progress value was 0.99f and it is coerced in `[0..1]`.
                 // Some of the velocity will be used for animation, but not all of it.
                 assertThat(consumedVelocity).isLessThan(0f)
                 assertThat(consumedVelocity).isGreaterThan(-velocityThreshold)
@@ -1037,9 +696,7 @@
 
     @Test
     fun scrollKeepPriorityEvenIfWeCanNoLongerScrollOnThatDirection() = runGestureTest {
-        // Overscrolling on scene B does nothing.
-        layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
+        val nestedScroll = nestedScrollConnection()
 
         // Overscroll is disabled, it will scroll up to 100%
         nestedScroll.scroll(available = upOffset(fractionOfScreen = 2f))
@@ -1061,7 +718,6 @@
         layoutState.transitions = transitions {
             defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy)
             from(SceneA, to = SceneB) {}
-            overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
         val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
@@ -1078,13 +734,11 @@
             onAnimationStart = {
                 assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.5f)
             },
-            expectedConsumedVelocity = -velocityThreshold,
         )
 
         // We didn't overscroll at the end of the transition.
         assertIdle(SceneB)
         assertThat(transition).hasProgress(1f)
-        assertThat(transition).hasNoOverscrollSpec()
     }
 
     @Test
@@ -1093,7 +747,6 @@
         layoutState.transitions = transitions {
             defaultSwipeSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy)
             from(SceneA, to = SceneC) {}
-            overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
         val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
@@ -1110,13 +763,11 @@
             onAnimationStart = {
                 assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.5f)
             },
-            expectedConsumedVelocity = velocityThreshold,
         )
 
         // We didn't overscroll at the end of the transition.
         assertIdle(SceneC)
         assertThat(transition).hasProgress(1f)
-        assertThat(transition).hasNoOverscrollSpec()
     }
 
     @Test
@@ -1124,31 +775,33 @@
         // Make scene B overscrollable.
         layoutState.transitions = transitions {
             from(SceneA, to = SceneB) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) }
-            overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
         val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
 
-        val dragController = onDragStarted(pointersInfo = middle, overSlop = up(1.5f))
+        val dragController =
+            onDragStarted(
+                pointersInfo = middle,
+                overSlop = up(1.5f),
+                expectedConsumedOverSlop = up(1f),
+            )
         val transition = assertThat(transitionState).isSceneTransition()
         assertThat(transition).hasFromScene(SceneA)
         assertThat(transition).hasToScene(SceneB)
-        assertThat(transition).hasProgress(1.5f)
+        assertThat(transition).hasProgress(1f)
 
         // Release to B.
         dragController.onDragStoppedAnimateNow(
             velocity = 0f,
             onAnimationStart = {
-                assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1.5f)
+                assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
             },
-            expectedConsumedVelocity = 0f,
         )
 
         // We kept the overscroll at 100% so that the placement logic didn't change at the end of
         // the animation.
         assertIdle(SceneB)
         assertThat(transition).hasProgress(1f)
-        assertThat(transition).hasOverscrollSpec()
     }
 
     @Test
@@ -1156,31 +809,33 @@
         // Make scene C overscrollable.
         layoutState.transitions = transitions {
             from(SceneA, to = SceneC) { spec = spring(dampingRatio = Spring.DampingRatioNoBouncy) }
-            overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) }
         }
 
         val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
 
-        val dragController = onDragStarted(pointersInfo = middle, overSlop = down(1.5f))
+        val dragController =
+            onDragStarted(
+                pointersInfo = middle,
+                overSlop = down(1.5f),
+                expectedConsumedOverSlop = down(1f),
+            )
         val transition = assertThat(transitionState).isSceneTransition()
         assertThat(transition).hasFromScene(SceneA)
         assertThat(transition).hasToScene(SceneC)
-        assertThat(transition).hasProgress(1.5f)
+        assertThat(transition).hasProgress(1f)
 
         // Release to C.
         dragController.onDragStoppedAnimateNow(
             velocity = 0f,
             onAnimationStart = {
-                assertTransition(fromScene = SceneA, toScene = SceneC, progress = 1.5f)
+                assertTransition(fromScene = SceneA, toScene = SceneC, progress = 1f)
             },
-            expectedConsumedVelocity = 0f,
         )
 
         // We kept the overscroll at 100% so that the placement logic didn't change at the end of
         // the animation.
         assertIdle(SceneC)
         assertThat(transition).hasProgress(1f)
-        assertThat(transition).hasOverscrollSpec()
     }
 
     @Test
@@ -1196,7 +851,6 @@
             onAnimationStart = {
                 assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.9f)
             },
-            expectedConsumedVelocity = 0f,
         )
         assertIdle(SceneA)
 
@@ -1207,7 +861,6 @@
             onAnimationStart = {
                 assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
             },
-            expectedConsumedVelocity = 0f,
         )
         assertIdle(SceneB)
     }
@@ -1234,7 +887,6 @@
         controller.onDragStoppedAnimateNow(
             velocity = velocityThreshold,
             onAnimationStart = { assertThat(transition).hasCurrentOverlays(OverlayA) },
-            expectedConsumedVelocity = velocityThreshold,
         )
         assertThat(layoutState.transitionState).isIdle()
         assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
@@ -1264,7 +916,6 @@
         controller.onDragStoppedAnimateNow(
             velocity = -velocityThreshold,
             onAnimationStart = { assertThat(transition).hasCurrentOverlays(/* empty */ ) },
-            expectedConsumedVelocity = -velocityThreshold,
         )
         assertThat(layoutState.transitionState).isIdle()
         assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
@@ -1294,7 +945,6 @@
         controller.onDragStoppedAnimateNow(
             velocity = velocityThreshold,
             onAnimationStart = { assertThat(transition).hasCurrentOverlays(OverlayB) },
-            expectedConsumedVelocity = velocityThreshold,
         )
         assertThat(layoutState.transitionState).isIdle()
         assertThat(layoutState.transitionState).hasCurrentScene(SceneA)
@@ -1313,7 +963,7 @@
 
         // Swipe down to replace overlay A by overlay B.
 
-        val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
+        val nestedScroll = nestedScrollConnection()
         nestedScroll.scroll(downOffset(0.1f))
         val transition = assertThat(layoutState.transitionState).isReplaceOverlayTransition()
         assertThat(transition).hasCurrentScene(SceneA)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index ffba639..6769032 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -17,8 +17,6 @@
 package com.android.compose.animation.scene
 
 import androidx.compose.animation.core.LinearEasing
-import androidx.compose.animation.core.Spring
-import androidx.compose.animation.core.spring
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.rememberScrollableState
@@ -33,7 +31,6 @@
 import androidx.compose.foundation.overscroll
 import androidx.compose.foundation.pager.HorizontalPager
 import androidx.compose.foundation.pager.PagerState
-import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.SideEffect
@@ -57,7 +54,6 @@
 import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
 import androidx.compose.ui.test.hasParent
 import androidx.compose.ui.test.hasTestTag
-import androidx.compose.ui.test.hasText
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onRoot
@@ -74,7 +70,6 @@
 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.content.state.TransitionState
 import com.android.compose.animation.scene.effect.OffsetOverscrollEffect
 import com.android.compose.animation.scene.subjects.assertThat
 import com.android.compose.test.assertSizeIsEqualTo
@@ -653,122 +648,6 @@
         rule.onNode(isElement(TestElements.Foo)).assertSizeIsEqualTo(20.dp, 20.dp)
     }
 
-    private fun setupOverscrollScenario(
-        layoutWidth: Dp,
-        layoutHeight: Dp,
-        sceneTransitions: SceneTransitionsBuilder.() -> Unit,
-        firstScroll: Float,
-        animatedFloatRange: ClosedFloatingPointRange<Float>,
-        onAnimatedFloat: (Float) -> Unit,
-    ): MutableSceneTransitionLayoutStateImpl {
-        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
-        // detected as a drag event.
-        var touchSlop = 0f
-
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    initialScene = SceneA,
-                    transitions = transitions(sceneTransitions),
-                )
-                    as MutableSceneTransitionLayoutStateImpl
-            }
-
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(
-                state = state,
-                modifier = Modifier.size(layoutWidth, layoutHeight),
-            ) {
-                scene(key = SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
-                    animateContentFloatAsState(
-                        value = animatedFloatRange.start,
-                        key = TestValues.Value1,
-                        false,
-                    )
-                    Spacer(Modifier.fillMaxSize())
-                }
-                scene(SceneB) {
-                    val animatedFloat by
-                        animateContentFloatAsState(
-                            value = animatedFloatRange.endInclusive,
-                            key = TestValues.Value1,
-                            canOverflow = false,
-                        )
-                    Spacer(Modifier.element(TestElements.Foo).fillMaxSize())
-                    LaunchedEffect(Unit) {
-                        snapshotFlow { animatedFloat }.collect { onAnimatedFloat(it) }
-                    }
-                }
-            }
-        }
-
-        assertThat(state.transitionState).isIdle()
-
-        // Swipe by half of verticalSwipeDistance.
-        rule.onRoot().performTouchInput {
-            val middleTop = Offset((layoutWidth / 2).toPx(), 0f)
-            down(middleTop)
-            val firstScrollHeight = layoutHeight.toPx() * firstScroll
-            moveBy(Offset(0f, touchSlop + firstScrollHeight), delayMillis = 1_000)
-        }
-        return state
-    }
-
-    @Test
-    fun elementTransitionDuringOverscrollWithOverscrollDSL() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        val overscrollTranslateY = 10.dp
-        var animatedFloat = 0f
-
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    overscroll(SceneB, Orientation.Vertical) {
-                        progressConverter = ProgressConverter.linear()
-                        // On overscroll 100% -> Foo should translate by overscrollTranslateY
-                        translate(TestElements.Foo, y = overscrollTranslateY)
-                    }
-                },
-                firstScroll = 0.5f, // Scroll 50%
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).isNotNull()
-        assertThat(transition).hasProgress(0.5f)
-        assertThat(animatedFloat).isEqualTo(50f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        // Scroll 150% (Scene B overscroll by 50%)
-        assertThat(transition).hasProgress(1.5f)
-        assertThat(transition).hasOverscrollSpec()
-        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)
-        // animatedFloat cannot overflow (canOverflow = false)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        // Scroll 250% (Scene B overscroll by 150%)
-        assertThat(transition).hasProgress(2.5f)
-        assertThat(transition).hasOverscrollSpec()
-        fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 1.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
     private fun expectedOffset(currentOffset: Dp, density: Density): Dp {
         return with(density) {
             OffsetOverscrollEffect.computeOffset(density, currentOffset.toPx()).toDp()
@@ -784,13 +663,7 @@
         // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
         // detected as a drag event.
         var touchSlop = 0f
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    initialScene = SceneA,
-                    transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(initialScene = SceneA) }
         rule.setContent {
             density = LocalDensity.current
             touchSlop = LocalViewConfiguration.current.touchSlop
@@ -845,17 +718,7 @@
         // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
         // detected as a drag event.
         var touchSlop = 0f
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    initialScene = SceneA,
-                    transitions =
-                        transitions {
-                            overscrollDisabled(SceneA, Orientation.Vertical)
-                            overscrollDisabled(SceneB, Orientation.Vertical)
-                        },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(initialScene = SceneA) }
         rule.setContent {
             density = LocalDensity.current
             touchSlop = LocalViewConfiguration.current.touchSlop
@@ -950,17 +813,7 @@
         // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
         // detected as a drag event.
         var touchSlop = 0f
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    initialScene = SceneA,
-                    transitions =
-                        transitions {
-                            defaultOverscrollProgressConverter = ProgressConverter.linear()
-                            overscrollDisabled(SceneB, Orientation.Vertical)
-                        },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(initialScene = SceneA) }
         rule.setContent {
             density = LocalDensity.current
             touchSlop = LocalViewConfiguration.current.touchSlop
@@ -1013,13 +866,7 @@
         val layoutWidth = 200.dp
         val layoutHeight = 400.dp
 
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    initialScene = SceneA,
-                    transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutState(initialScene = SceneA) }
 
         rule.setContent {
             density = LocalDensity.current
@@ -1146,262 +993,6 @@
     }
 
     @Test
-    fun elementTransitionWithDistanceDuringOverscroll() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        var animatedFloat = 0f
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    overscroll(SceneB, Orientation.Vertical) {
-                        progressConverter = ProgressConverter.linear()
-                        // On overscroll 100% -> Foo should translate by layoutHeight
-                        translate(TestElements.Foo, y = { absoluteDistance })
-                    }
-                },
-                firstScroll = 1f, // 100% scroll
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 50%
-            moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
-        }
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        // Scroll 150% (100% scroll + 50% overscroll)
-        assertThat(transition).hasProgress(1.5f)
-        assertThat(transition).hasOverscrollSpec()
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        // Scroll 250% (100% scroll + 150% overscroll)
-        assertThat(transition).hasProgress(2.5f)
-        assertThat(transition).hasOverscrollSpec()
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 1.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
-    @Test
-    fun elementTransitionWithDistanceDuringOverscrollWithDefaultProgressConverter() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        var animatedFloat = 0f
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    // Overscroll progress will be halved
-                    defaultOverscrollProgressConverter = ProgressConverter { it / 2f }
-
-                    overscroll(SceneB, Orientation.Vertical) {
-                        // On overscroll 100% -> Foo should translate by layoutHeight
-                        translate(TestElements.Foo, y = { absoluteDistance })
-                    }
-                },
-                firstScroll = 1f, // 100% scroll
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        // Scroll 200% (100% scroll + 100% overscroll)
-        assertThat(transition).hasProgress(2f)
-        assertThat(transition).hasOverscrollSpec()
-
-        // Overscroll progress is halved, we are at 50% of the overscroll progress.
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
-    @Test
-    fun elementTransitionWithDistanceDuringOverscrollWithOverrideDefaultProgressConverter() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        var animatedFloat = 0f
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    // Overscroll progress will be linear (by default)
-                    defaultOverscrollProgressConverter = ProgressConverter.linear()
-
-                    overscroll(SceneB, Orientation.Vertical) {
-                        // This override the defaultOverscrollProgressConverter
-                        // Overscroll progress will be halved
-                        progressConverter = ProgressConverter { it / 2f }
-                        // On overscroll 100% -> Foo should translate by layoutHeight
-                        translate(TestElements.Foo, y = { absoluteDistance })
-                    }
-                },
-                firstScroll = 1f, // 100% scroll
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        // Scroll 200% (100% scroll + 100% overscroll)
-        assertThat(transition).hasProgress(2f)
-        assertThat(transition).hasOverscrollSpec()
-
-        // Overscroll progress is halved, we are at 50% of the overscroll progress.
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
-    @Test
-    fun elementTransitionWithDistanceDuringOverscrollWithProgressConverter() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        var animatedFloat = 0f
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    overscroll(SceneB, Orientation.Vertical) {
-                        // Overscroll progress will be halved
-                        progressConverter = ProgressConverter { it / 2f }
-
-                        // On overscroll 100% -> Foo should translate by layoutHeight
-                        translate(TestElements.Foo, y = { absoluteDistance })
-                    }
-                },
-                firstScroll = 1f, // 100% scroll
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        // Scroll 200% (100% scroll + 100% overscroll)
-        assertThat(transition).hasProgress(2f)
-        assertThat(transition).hasOverscrollSpec()
-
-        // Overscroll progress is halved, we are at 50% of the overscroll progress.
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 100%
-            moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
-        }
-
-        // Scroll 300% (100% scroll + 200% overscroll)
-        assertThat(transition).hasProgress(3f)
-        assertThat(transition).hasOverscrollSpec()
-
-        // Overscroll progress is halved, we are at 100% of the overscroll progress.
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
-    @Test
-    fun elementTransitionWithDistanceDuringOverscrollBouncing() {
-        val layoutWidth = 200.dp
-        val layoutHeight = 400.dp
-        var animatedFloat = 0f
-        val state =
-            setupOverscrollScenario(
-                layoutWidth = layoutWidth,
-                layoutHeight = layoutHeight,
-                sceneTransitions = {
-                    defaultSwipeSpec =
-                        spring(
-                            dampingRatio = Spring.DampingRatioMediumBouncy,
-                            stiffness = Spring.StiffnessLow,
-                        )
-
-                    overscroll(SceneB, Orientation.Vertical) {
-                        progressConverter = ProgressConverter.linear()
-                        // On overscroll 100% -> Foo should translate by layoutHeight
-                        translate(TestElements.Foo, y = { absoluteDistance })
-                    }
-                },
-                firstScroll = 1f, // 100% scroll
-                animatedFloatRange = 0f..100f,
-                onAnimatedFloat = { animatedFloat = it },
-            )
-
-        val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
-        fooElement.assertTopPositionInRootIsEqualTo(0.dp)
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        rule.onRoot().performTouchInput {
-            // Scroll another 50%
-            moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
-        }
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-
-        // Scroll 150% (100% scroll + 50% overscroll)
-        assertThat(transition).hasProgress(1.5f)
-        assertThat(transition).hasOverscrollSpec()
-        fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * (transition.progress - 1f))
-        assertThat(animatedFloat).isEqualTo(100f)
-
-        // finger raised
-        rule.onRoot().performTouchInput { up() }
-
-        // The target value is 1f, but the spring (defaultSwipeSpec) allows you to go to a lower
-        // value.
-        rule.waitUntil(timeoutMillis = 10_000) { transition.progress < 1f }
-
-        assertThat(transition.progress).isLessThan(1f)
-        assertThat(transition).hasOverscrollSpec()
-        assertThat(transition).hasBouncingContent(transition.toContent)
-        assertThat(animatedFloat).isEqualTo(100f)
-    }
-
-    @Test
     fun elementIsUsingLastTransition() {
         // 4 frames of animation.
         val duration = 4 * 16
@@ -1848,13 +1439,7 @@
     @Test
     fun targetStateIsSetEvenWhenNotPlaced() {
         // Start directly at A => B but with progress < 0f to overscroll on A.
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions { overscrollDisabled(SceneA, Orientation.Horizontal) },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateImpl(SceneA) }
 
         lateinit var layoutImpl: SceneTransitionLayoutImpl
         val scope =
@@ -1870,14 +1455,7 @@
             }
 
         scope.launch {
-            state.startTransition(
-                transition(
-                    from = SceneA,
-                    to = SceneB,
-                    progress = { -1f },
-                    orientation = Orientation.Horizontal,
-                )
-            )
+            state.startTransition(transition(from = SceneA, to = SceneB, progress = { -1f }))
         }
         rule.waitForIdle()
 
@@ -2004,204 +1582,6 @@
     }
 
     @Test
-    fun sharedElementIsOnlyPlacedInOverscrollingScene() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions {
-                        overscrollDisabled(SceneA, Orientation.Horizontal)
-                        overscrollDisabled(SceneB, Orientation.Horizontal)
-                    },
-                )
-            }
-
-        @Composable
-        fun ContentScope.Foo() {
-            Box(Modifier.element(TestElements.Foo).size(10.dp))
-        }
-
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayout(state) {
-                    scene(SceneA) { Foo() }
-                    scene(SceneB) { Foo() }
-                }
-            }
-
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertDoesNotExist()
-
-        // A => B while overscrolling at scene B.
-        var progress by mutableStateOf(2f)
-        scope.launch {
-            state.startTransition(transition(from = SceneA, to = SceneB, progress = { progress }))
-        }
-        rule.waitForIdle()
-
-        // Foo should only be placed in scene B.
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertExists().assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsDisplayed()
-
-        // Overscroll at scene A.
-        progress = -1f
-        rule.waitForIdle()
-
-        // Foo should only be placed in scene A.
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertExists().assertIsNotDisplayed()
-    }
-
-    @Test
-    fun sharedMovableElementIsOnlyComposedInOverscrollingScene() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions {
-                        overscrollDisabled(SceneA, Orientation.Horizontal)
-                        overscrollDisabled(SceneB, Orientation.Horizontal)
-                    },
-                )
-            }
-
-        val fooInA = "fooInA"
-        val fooInB = "fooInB"
-
-        val key = MovableElementKey("Foo", contents = setOf(SceneA, SceneB))
-
-        @Composable
-        fun ContentScope.MovableFoo(text: String, modifier: Modifier = Modifier) {
-            MovableElement(key, modifier) { content { Text(text) } }
-        }
-
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayout(state) {
-                    scene(SceneA) { MovableFoo(text = fooInA) }
-                    scene(SceneB) { MovableFoo(text = fooInB) }
-                }
-            }
-
-        rule.onNode(hasText(fooInA)).assertIsDisplayed()
-        rule.onNode(hasText(fooInB)).assertDoesNotExist()
-
-        // A => B while overscrolling at scene B.
-        var progress by mutableStateOf(2f)
-        scope.launch {
-            state.startTransition(transition(from = SceneA, to = SceneB, progress = { progress }))
-        }
-        rule.waitForIdle()
-
-        // Foo content should only be composed in scene B.
-        rule.onNode(hasText(fooInA)).assertDoesNotExist()
-        rule.onNode(hasText(fooInB)).assertIsDisplayed()
-
-        // Overscroll at scene A.
-        progress = -1f
-        rule.waitForIdle()
-
-        // Foo content should only be composed in scene A.
-        rule.onNode(hasText(fooInA)).assertIsDisplayed()
-        rule.onNode(hasText(fooInB)).assertDoesNotExist()
-    }
-
-    @Test
-    fun interruptionThenOverscroll() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions {
-                        overscroll(SceneB, Orientation.Vertical) {
-                            progressConverter = ProgressConverter.linear()
-                            translate(TestElements.Foo, y = 15.dp)
-                        }
-                    },
-                )
-            }
-
-        @Composable
-        fun ContentScope.SceneWithFoo(offset: DpOffset, modifier: Modifier = Modifier) {
-            Box(modifier.fillMaxSize()) {
-                Box(Modifier.offset(offset.x, offset.y).element(TestElements.Foo).size(100.dp))
-            }
-        }
-
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayout(state, Modifier.size(200.dp)) {
-                    scene(SceneA) { SceneWithFoo(offset = DpOffset.Zero) }
-                    scene(SceneB) { SceneWithFoo(offset = DpOffset(x = 40.dp, y = 0.dp)) }
-                    scene(SceneC) { SceneWithFoo(offset = DpOffset(x = 40.dp, y = 40.dp)) }
-                }
-            }
-
-        // Start A => B at 75%.
-        scope.launch {
-            state.startTransition(
-                transition(
-                    from = SceneA,
-                    to = SceneB,
-                    progress = { 0.75f },
-                    onFreezeAndAnimate = { /* never finish */ },
-                )
-            )
-        }
-
-        // Foo should be at offset (30dp, 0dp) and placed in scene B.
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertPositionInRootIsEqualTo(30.dp, 0.dp)
-        rule.onNode(isElement(TestElements.Foo, SceneC)).assertIsNotDisplayed()
-
-        // Interrupt A => B with B => C at 0%.
-        var progress by mutableStateOf(0f)
-        var interruptionProgress by mutableStateOf(1f)
-        scope.launch {
-            state.startTransition(
-                transition(
-                    from = SceneB,
-                    to = SceneC,
-                    progress = { progress },
-                    interruptionProgress = { interruptionProgress },
-                    orientation = Orientation.Vertical,
-                    onFreezeAndAnimate = { /* never finish */ },
-                )
-            )
-        }
-
-        // Because interruption progress is at 100M, Foo should still be at offset (30dp, 0dp) but
-        // placed in scene C.
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneC)).assertPositionInRootIsEqualTo(30.dp, 0.dp)
-
-        // Overscroll B => C on scene B at -100%. Because overscrolling on B => C translates Foo
-        // vertically by -15dp and that interruptionProgress is still 100%, we should now be at
-        // (30dp, -15dp)
-        progress = -1f
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed()
-        rule
-            .onNode(isElement(TestElements.Foo, SceneB))
-            .assertPositionInRootIsEqualTo(30.dp, -15.dp)
-        rule.onNode(isElement(TestElements.Foo, SceneC)).assertIsNotDisplayed()
-
-        // Finish the interruption, we should now be at (40dp, -15dp), still on scene B.
-        interruptionProgress = 0f
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed()
-        rule
-            .onNode(isElement(TestElements.Foo, SceneB))
-            .assertPositionInRootIsEqualTo(40.dp, -15.dp)
-        rule.onNode(isElement(TestElements.Foo, SceneC)).assertIsNotDisplayed()
-
-        // Finish the transition, we should be at the final position (40dp, 40dp) on scene C.
-        progress = 1f
-        rule.onNode(isElement(TestElements.Foo, SceneA)).assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneB)).assertIsNotDisplayed()
-        rule.onNode(isElement(TestElements.Foo, SceneC)).assertPositionInRootIsEqualTo(40.dp, 40.dp)
-    }
-
-    @Test
     fun lastPlacementValuesAreClearedOnNestedElements() {
         val state = rule.runOnIdle { MutableSceneTransitionLayoutStateImpl(SceneA) }
 
@@ -2397,53 +1777,6 @@
     }
 
     @Test
-    fun lastSizeIsUnspecifiedWhenOverscrollingOtherScene() {
-        val state =
-            rule.runOnIdle {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions { overscrollDisabled(SceneA, Orientation.Horizontal) },
-                )
-            }
-
-        @Composable
-        fun ContentScope.Foo() {
-            Box(Modifier.element(TestElements.Foo).size(10.dp))
-        }
-
-        lateinit var layoutImpl: SceneTransitionLayoutImpl
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayoutForTesting(state, onLayoutImpl = { layoutImpl = it }) {
-                    scene(SceneA) { Foo() }
-                    scene(SceneB) { Foo() }
-                }
-            }
-
-        // Overscroll A => B on A.
-        scope.launch {
-            state.startTransition(
-                transition(
-                    from = SceneA,
-                    to = SceneB,
-                    progress = { -1f },
-                    onFreezeAndAnimate = { /* never finish */ },
-                )
-            )
-        }
-        rule.waitForIdle()
-
-        assertThat(
-                layoutImpl.elements
-                    .getValue(TestElements.Foo)
-                    .stateByContent
-                    .getValue(SceneB)
-                    .lastSize
-            )
-            .isEqualTo(Element.SizeUnspecified)
-    }
-
-    @Test
     fun transparentElementIsNotImpactingInterruption() {
         val state =
             rule.runOnIdle {
@@ -2853,7 +2186,6 @@
         // Start an overscrollable transition driven by progress.
         var progress by mutableFloatStateOf(0f)
         val transition = transition(from = SceneA, to = SceneB, progress = { progress })
-        assertThat(transition).isInstanceOf(TransitionState.DirectionProperties::class.java)
         scope.launch { state.startTransition(transition) }
 
         // Reset the counters after the first animation frame.
@@ -2876,6 +2208,7 @@
     }
 
     @Test
+    @Ignore("b/363964445")
     fun interruption_considerPreviousUniqueState() {
         @Composable
         fun SceneScope.Foo(modifier: Modifier = Modifier) {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt
deleted file mode 100644
index 37dae39..0000000
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt
+++ /dev/null
@@ -1,318 +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.compose.animation.scene
-
-import androidx.compose.foundation.gestures.Orientation.Vertical
-import androidx.compose.foundation.gestures.rememberScrollableState
-import androidx.compose.foundation.gestures.scrollable
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.platform.LocalViewConfiguration
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onRoot
-import androidx.compose.ui.test.performTouchInput
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
-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.subjects.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class NestedScrollToSceneTest {
-    @get:Rule val rule = createComposeRule()
-
-    private var touchSlop = 0f
-    private val layoutWidth: Dp = 200.dp
-    private val layoutHeight = 400.dp
-
-    private fun setup2ScenesAndScrollTouchSlop(
-        modifierSceneA: @Composable ContentScope.() -> Modifier = { Modifier }
-    ): MutableSceneTransitionLayoutState {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(SceneA, transitions = EmptyTestTransitions)
-            }
-
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(
-                state = state,
-                modifier = Modifier.size(layoutWidth, layoutHeight),
-            ) {
-                scene(SceneA, userActions = mapOf(Swipe.Up to SceneB)) {
-                    Spacer(modifierSceneA().fillMaxSize())
-                }
-                scene(SceneB, userActions = mapOf(Swipe.Down to SceneA)) {
-                    Spacer(Modifier.fillMaxSize())
-                }
-            }
-        }
-
-        pointerDownAndScrollTouchSlop()
-
-        assertThat(state.transitionState).isIdle()
-
-        return state
-    }
-
-    private fun pointerDownAndScrollTouchSlop() {
-        rule.onRoot().performTouchInput {
-            val middleTop = Offset((layoutWidth / 2).toPx(), 0f)
-            down(middleTop)
-            // Scroll touchSlop
-            moveBy(Offset(0f, touchSlop), delayMillis = 1_000)
-        }
-    }
-
-    private fun scrollDown(percent: Float = 1f) {
-        rule.onRoot().performTouchInput {
-            moveBy(Offset(0f, layoutHeight.toPx() * percent), delayMillis = 1_000)
-        }
-    }
-
-    private fun scrollUp(percent: Float = 1f) = scrollDown(-percent)
-
-    private fun pointerUp() {
-        rule.onRoot().performTouchInput { up() }
-    }
-
-    @Test
-    fun scrollableElementsInSTL_shouldHavePriority() {
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier
-                // A scrollable that consumes the scroll gesture
-                .scrollable(rememberScrollableState { it }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-
-        // Consumed by the scrollable element
-        assertThat(state.transitionState).isIdle()
-    }
-
-    @Test
-    fun unconsumedScrollEvents_canBeConsumedBySTLByDefault() {
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier
-                // A scrollable that does not consume the scroll gesture
-                .scrollable(rememberScrollableState { 0f }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-        // STL will start a transition with the remaining scroll
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasProgress(0.5f)
-
-        scrollUp(percent = 1f)
-        assertThat(transition).hasProgress(1.5f)
-    }
-
-    @Test
-    fun customizeStlNestedScrollBehavior_EdgeNoPreview() {
-        var canScroll = true
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier.verticalNestedScrollToScene(
-                    bottomBehavior = NestedScrollBehavior.EdgeNoPreview
-                )
-                .scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-        assertThat(state.transitionState).isIdle()
-
-        // Reach the end of the scrollable element
-        canScroll = false
-        scrollUp(percent = 0.5f)
-        assertThat(state.transitionState).isIdle()
-
-        pointerUp()
-        assertThat(state.transitionState).isIdle()
-
-        // Start a new gesture
-        pointerDownAndScrollTouchSlop()
-        scrollUp(percent = 0.5f)
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasProgress(0.5f)
-
-        pointerUp()
-        rule.waitForIdle()
-        assertThat(state.transitionState).isIdle()
-        assertThat(state.transitionState).hasCurrentScene(SceneB)
-    }
-
-    @Test
-    fun customizeStlNestedScrollBehavior_EdgeWithPreview() {
-        var canScroll = true
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier.verticalNestedScrollToScene(
-                    bottomBehavior = NestedScrollBehavior.EdgeWithPreview
-                )
-                .scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-        assertThat(state.transitionState).isIdle()
-
-        // Reach the end of the scrollable element
-        canScroll = false
-        scrollUp(percent = 0.5f)
-        val transition1 = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition1).hasProgress(0.5f)
-
-        pointerUp()
-        rule.waitForIdle()
-        assertThat(state.transitionState).isIdle()
-        assertThat(state.transitionState).hasCurrentScene(SceneA)
-
-        // Start a new gesture
-        pointerDownAndScrollTouchSlop()
-        scrollUp(percent = 0.5f)
-        val transition2 = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition2).hasProgress(0.5f)
-
-        pointerUp()
-        rule.waitForIdle()
-        assertThat(state.transitionState).isIdle()
-        assertThat(state.transitionState).hasCurrentScene(SceneB)
-    }
-
-    @Test
-    fun customizeStlNestedScrollBehavior_EdgeAlways() {
-        var canScroll = true
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier.verticalNestedScrollToScene(bottomBehavior = NestedScrollBehavior.EdgeAlways)
-                .scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-        assertThat(state.transitionState).isIdle()
-
-        // Reach the end of the scrollable element
-        canScroll = false
-        scrollUp(percent = 0.5f)
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasProgress(0.5f)
-
-        pointerUp()
-        rule.waitForIdle()
-        assertThat(state.transitionState).isIdle()
-        assertThat(state.transitionState).hasCurrentScene(SceneB)
-    }
-
-    @Test
-    fun stlNotConsumeUnobservedGesture() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(SceneA, transitions = EmptyTestTransitions)
-            }
-
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(
-                state = state,
-                modifier = Modifier.size(layoutWidth, layoutHeight),
-            ) {
-                scene(SceneA) {
-                    Spacer(
-                        Modifier.verticalNestedScrollToScene()
-                            // This scrollable will not consume the gesture.
-                            .scrollable(rememberScrollableState { 0f }, Vertical)
-                            .fillMaxSize()
-                    )
-                }
-            }
-        }
-
-        rule.onRoot().performTouchInput {
-            down(Offset.Zero)
-            // There is no vertical scene.
-            moveBy(Offset(0f, layoutWidth.toPx()), delayMillis = 1_000)
-        }
-
-        rule.waitForIdle()
-        assertThat(state.transitionState).isIdle()
-    }
-
-    @Test
-    fun customizeStlNestedScrollBehavior_multipleRequests() {
-        var canScroll = true
-        val state = setup2ScenesAndScrollTouchSlop {
-            Modifier
-                // This verticalNestedScrollToScene is closer the STL (an ancestor node)
-                .verticalNestedScrollToScene(bottomBehavior = NestedScrollBehavior.EdgeAlways)
-                // Another verticalNestedScrollToScene modifier
-                .verticalNestedScrollToScene(bottomBehavior = NestedScrollBehavior.EdgeNoPreview)
-                .scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical)
-        }
-
-        scrollUp(percent = 0.5f)
-        assertThat(state.transitionState).isIdle()
-
-        // Reach the end of the scrollable element
-        canScroll = false
-
-        scrollUp(percent = 0.5f)
-        // EdgeAlways always consume the remaining scroll, EdgeNoPreview does not.
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasProgress(0.5f)
-    }
-
-    @Test
-    fun resetScrollTracking_afterMissingPointerUpEvent() {
-        var canScroll = true
-        var hasScrollable by mutableStateOf(true)
-        val state = setup2ScenesAndScrollTouchSlop {
-            if (hasScrollable) {
-                Modifier.scrollable(rememberScrollableState { if (canScroll) it else 0f }, Vertical)
-            } else {
-                Modifier
-            }
-        }
-
-        // The gesture is consumed by the component in the scene.
-        scrollUp(percent = 0.2f)
-
-        // STL keeps track of the scroll consumed. The scene remains in Idle.
-        assertThat(state.transitionState).isIdle()
-
-        // The scrollable component disappears, and does not send the signal (pointer up) to reset
-        // the consumed amount.
-        hasScrollable = false
-        pointerUp()
-
-        // A new scrollable component appears and allows the scene to consume the scroll.
-        hasScrollable = true
-        canScroll = false
-        pointerDownAndScrollTouchSlop()
-        scrollUp(percent = 0.2f)
-
-        // STL can only start the transition if it has reset the amount of scroll consumed.
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasProgress(0.2f)
-    }
-}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index 7ea414d..bad4c62 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -19,7 +19,6 @@
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.ScrollState
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
@@ -46,7 +45,6 @@
 import androidx.compose.ui.test.onRoot
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.test.swipe
-import androidx.compose.ui.test.swipeUp
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -56,7 +54,6 @@
 import com.android.compose.animation.scene.subjects.assertThat
 import com.android.compose.test.assertSizeIsEqualTo
 import com.android.compose.test.setContentAndCreateMainScope
-import com.android.compose.test.subjects.assertThat
 import com.android.compose.test.transition
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
@@ -745,18 +742,7 @@
 
     @Test
     fun overscrollingOverlay_movableElementNotInOverlay() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions {
-                        // Make OverlayA overscrollable.
-                        overscroll(OverlayA, orientation = Orientation.Horizontal) {
-                            translate(ElementKey("elementThatDoesNotExist"), x = 10.dp)
-                        }
-                    },
-                )
-            }
+        val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateImpl(SceneA) }
 
         val key = MovableElementKey("Foo", contents = setOf(SceneA))
         val movableElementChildTag = "movableElementChildTag"
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index 3b7d661..d1bd52b 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -17,8 +17,6 @@
 package com.android.compose.animation.scene
 
 import android.util.Log
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.compose.animation.scene.TestScenes.SceneA
@@ -27,7 +25,6 @@
 import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.subjects.assertThat
 import com.android.compose.animation.scene.transition.seekToScene
-import com.android.compose.test.MonotonicClockTestScope
 import com.android.compose.test.TestSceneTransition
 import com.android.compose.test.runMonotonicClockTest
 import com.android.compose.test.transition
@@ -166,115 +163,6 @@
         assertThat(state.currentTransition?.transformationSpec?.transformationMatchers).hasSize(2)
     }
 
-    private fun MonotonicClockTestScope.startOverscrollableTransistionFromAtoB(
-        progress: () -> Float,
-        sceneTransitions: SceneTransitions,
-    ): MutableSceneTransitionLayoutStateImpl {
-        val state = MutableSceneTransitionLayoutStateImpl(SceneA, sceneTransitions)
-        state.startTransitionImmediately(
-            animationScope = backgroundScope,
-            transition(
-                from = SceneA,
-                to = SceneB,
-                progress = progress,
-                orientation = Orientation.Vertical,
-            ),
-        )
-        assertThat(state.isTransitioning()).isTrue()
-        return state
-    }
-
-    @Test
-    fun overscrollDsl_definedForToScene() = runMonotonicClockTest {
-        val progress = mutableStateOf(0f)
-        val state =
-            startOverscrollableTransistionFromAtoB(
-                progress = { progress.value },
-                sceneTransitions =
-                    transitions {
-                        overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
-                    },
-            )
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneA is NOT defined
-        progress.value = -0.1f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // scroll from SceneA to SceneB
-        progress.value = 0.5f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        progress.value = 1f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneB is defined
-        progress.value = 1.1f
-        val overscrollSpec = assertThat(transition).hasOverscrollSpec()
-        assertThat(overscrollSpec.content).isEqualTo(SceneB)
-    }
-
-    @Test
-    fun overscrollDsl_definedForFromScene() = runMonotonicClockTest {
-        val progress = mutableStateOf(0f)
-        val state =
-            startOverscrollableTransistionFromAtoB(
-                progress = { progress.value },
-                sceneTransitions =
-                    transitions {
-                        overscroll(SceneA, Orientation.Vertical) { fade(TestElements.Foo) }
-                    },
-            )
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneA is defined
-        progress.value = -0.1f
-        val overscrollSpec = assertThat(transition).hasOverscrollSpec()
-        assertThat(overscrollSpec.content).isEqualTo(SceneA)
-
-        // scroll from SceneA to SceneB
-        progress.value = 0.5f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        progress.value = 1f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneB is NOT defined
-        progress.value = 1.1f
-        assertThat(transition).hasNoOverscrollSpec()
-    }
-
-    @Test
-    fun overscrollDsl_notDefinedScenes() = runMonotonicClockTest {
-        val progress = mutableStateOf(0f)
-        val state =
-            startOverscrollableTransistionFromAtoB(
-                progress = { progress.value },
-                sceneTransitions = transitions {},
-            )
-
-        val transition = assertThat(state.transitionState).isSceneTransition()
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneA is NOT defined
-        progress.value = -0.1f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // scroll from SceneA to SceneB
-        progress.value = 0.5f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        progress.value = 1f
-        assertThat(transition).hasNoOverscrollSpec()
-
-        // overscroll for SceneB is NOT defined
-        progress.value = 1.1f
-        assertThat(transition).hasNoOverscrollSpec()
-    }
-
     @Test
     fun multipleTransitions() = runTest {
         val frozenTransitions = mutableSetOf<TestSceneTransition>()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index b00b894b..fdbd0f6 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -20,7 +20,6 @@
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.tween
 import androidx.compose.foundation.background
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.offset
@@ -28,7 +27,6 @@
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
@@ -55,13 +53,11 @@
 import com.android.compose.animation.scene.TestScenes.SceneC
 import com.android.compose.animation.scene.subjects.assertThat
 import com.android.compose.test.assertSizeIsEqualTo
-import com.android.compose.test.setContentAndCreateMainScope
 import com.android.compose.test.subjects.DpOffsetSubject
 import com.android.compose.test.subjects.assertThat
 import com.android.compose.test.transition
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
 import org.junit.Assert.assertThrows
 import org.junit.Rule
 import org.junit.Test
@@ -311,43 +307,6 @@
     }
 
     @Test
-    fun layoutSizeDoesNotOverscrollWhenOverscrollIsSpecified() {
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutStateImpl(
-                    SceneA,
-                    transitions { overscrollDisabled(SceneB, Orientation.Horizontal) },
-                )
-            }
-
-        val layoutTag = "layout"
-        val scope =
-            rule.setContentAndCreateMainScope {
-                SceneTransitionLayout(state, Modifier.testTag(layoutTag)) {
-                    scene(SceneA) { Box(Modifier.size(50.dp)) }
-                    scene(SceneB) { Box(Modifier.size(70.dp)) }
-                }
-            }
-
-        // Overscroll on A at -100%: size should be interpolated given that there is no overscroll
-        // defined for scene A.
-        var progress by mutableStateOf(-1f)
-        scope.launch {
-            state.startTransition(transition(from = SceneA, to = SceneB, progress = { progress }))
-        }
-        rule.onNodeWithTag(layoutTag).assertSizeIsEqualTo(30.dp)
-
-        // Middle of the transition.
-        progress = 0.5f
-        rule.onNodeWithTag(layoutTag).assertSizeIsEqualTo(60.dp)
-
-        // Overscroll on B at 200%: size should not be interpolated given that there is an
-        // overscroll defined for scene B.
-        progress = 2f
-        rule.onNodeWithTag(layoutTag).assertSizeIsEqualTo(70.dp)
-    }
-
-    @Test
     fun multipleTransitionsWillComposeMultipleScenes() {
         val duration = 10 * 16L
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index fe7b5b6..9135fdd 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -35,9 +35,6 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import androidx.compose.ui.input.nestedscroll.NestedScrollSource
-import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.input.pointer.PointerType
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.platform.LocalViewConfiguration
@@ -735,46 +732,6 @@
     }
 
     @Test
-    fun overscrollScopeExtendsDensity() {
-        val swipeDistance = 100.dp
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    SceneA,
-                    transitions {
-                        from(SceneA, to = SceneB) { distance = FixedDistance(swipeDistance) }
-
-                        overscroll(SceneB, Orientation.Vertical) {
-                            progressConverter = ProgressConverter.linear()
-                            translate(TestElements.Foo, x = { 20.dp.toPx() }, y = { 30.dp.toPx() })
-                        }
-                    },
-                )
-            }
-        val layoutSize = 200.dp
-        var touchSlop = 0f
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(state, Modifier.size(layoutSize)) {
-                scene(SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
-                    Box(Modifier.fillMaxSize())
-                }
-                scene(SceneB) { Box(Modifier.element(TestElements.Foo).fillMaxSize()) }
-            }
-        }
-
-        // Swipe down by twice the swipe distance so that we are at 100% overscrolling on scene B.
-        rule.onRoot().performTouchInput {
-            val middle = (layoutSize / 2).toPx()
-            down(Offset(middle, middle))
-            moveBy(Offset(0f, touchSlop + (swipeDistance * 2).toPx()), delayMillis = 1_000)
-        }
-
-        // Foo should be translated by (20dp, 30dp).
-        rule.onNode(isElement(TestElements.Foo)).assertPositionInRootIsEqualTo(20.dp, 30.dp)
-    }
-
-    @Test
     fun startEnd_ltrLayout() {
         val state =
             rule.runOnUiThread {
@@ -923,128 +880,6 @@
     }
 
     @Test
-    fun whenOverscrollIsDisabled_dragGestureShouldNotBeConsumed() {
-        val swipeDistance = 100.dp
-
-        var availableOnPostScroll = Float.MIN_VALUE
-        val connection =
-            object : NestedScrollConnection {
-                override fun onPostScroll(
-                    consumed: Offset,
-                    available: Offset,
-                    source: NestedScrollSource,
-                ): Offset {
-                    availableOnPostScroll = available.y
-                    return super.onPostScroll(consumed, available, source)
-                }
-            }
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    SceneA,
-                    transitions {
-                        from(SceneA, to = SceneB) { distance = FixedDistance(swipeDistance) }
-                        overscrollDisabled(SceneB, Orientation.Vertical)
-                    },
-                )
-            }
-        val layoutSize = 200.dp
-        var touchSlop = 0f
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(state, Modifier.size(layoutSize).nestedScroll(connection)) {
-                scene(SceneA, userActions = mapOf(Swipe.Down to SceneB)) {
-                    Box(Modifier.fillMaxSize())
-                }
-                scene(SceneB) { Box(Modifier.element(TestElements.Foo).fillMaxSize()) }
-            }
-        }
-
-        // Swipe down by the swipe distance so that we are on scene B.
-        rule.onRoot().performTouchInput {
-            val middle = (layoutSize / 2).toPx()
-            down(Offset(middle, middle))
-            moveBy(Offset(0f, touchSlop + (swipeDistance).toPx()), delayMillis = 1_000)
-        }
-        val transition = state.currentTransition
-        assertThat(transition).isNotNull()
-        assertThat(transition!!.progress).isEqualTo(1f)
-        assertThat(availableOnPostScroll).isEqualTo(0f)
-
-        // Overscrolling on Scene B
-        val ovescrollPx = 100f
-        rule.onRoot().performTouchInput { moveBy(Offset(0f, ovescrollPx), delayMillis = 1_000) }
-        // Overscroll is disabled on Scene B
-        assertThat(transition.progress).isEqualTo(1f)
-        assertThat(availableOnPostScroll).isEqualTo(ovescrollPx)
-    }
-
-    @Test
-    fun scrollKeepPriorityEvenIfWeCanNoLongerScrollOnThatDirection() {
-        val swipeDistance = 100.dp
-        val state =
-            rule.runOnUiThread {
-                MutableSceneTransitionLayoutState(
-                    SceneA,
-                    transitions {
-                        from(SceneA, to = SceneB) { distance = FixedDistance(swipeDistance) }
-                        from(SceneB, to = SceneC) { distance = FixedDistance(swipeDistance) }
-                        overscrollDisabled(SceneB, Orientation.Vertical)
-                    },
-                )
-            }
-        val layoutSize = 200.dp
-        var touchSlop = 0f
-        rule.setContent {
-            touchSlop = LocalViewConfiguration.current.touchSlop
-            SceneTransitionLayout(state, Modifier.size(layoutSize)) {
-                scene(SceneA, userActions = mapOf(Swipe.Down to SceneB, Swipe.Right to SceneC)) {
-                    Box(
-                        Modifier.fillMaxSize()
-                            // A scrollable that does not consume the scroll gesture
-                            .scrollable(rememberScrollableState { 0f }, Orientation.Vertical)
-                    )
-                }
-                scene(SceneB, userActions = mapOf(Swipe.Right to SceneC)) {
-                    Box(Modifier.element(TestElements.Foo).fillMaxSize())
-                }
-                scene(SceneC) { Box(Modifier.fillMaxSize()) }
-            }
-        }
-
-        fun assertTransition(from: SceneKey, to: SceneKey, progress: Float) {
-            val transition = assertThat(state.transitionState).isSceneTransition()
-            assertThat(transition).hasFromScene(from)
-            assertThat(transition).hasToScene(to)
-            assertThat(transition.progress).isEqualTo(progress)
-        }
-
-        // Vertical scroll 100%
-        rule.onRoot().performTouchInput {
-            val middle = (layoutSize / 2).toPx()
-            down(Offset(middle, middle))
-            moveBy(Offset(0f, y = touchSlop + swipeDistance.toPx()), delayMillis = 1_000)
-        }
-        assertTransition(from = SceneA, to = SceneB, progress = 1f)
-
-        // Continue vertical scroll, should be ignored (overscrollDisabled)
-        rule.onRoot().performTouchInput { moveBy(Offset(0f, y = touchSlop), delayMillis = 1_000) }
-        assertTransition(from = SceneA, to = SceneB, progress = 1f)
-
-        // Horizontal scroll, should be ignored
-        rule.onRoot().performTouchInput {
-            moveBy(Offset(x = touchSlop + swipeDistance.toPx(), 0f), delayMillis = 1_000)
-        }
-        assertTransition(from = SceneA, to = SceneB, progress = 1f)
-
-        // Vertical scroll, in the opposite direction
-        rule.onRoot().performTouchInput {
-            moveBy(Offset(0f, -swipeDistance.toPx()), delayMillis = 1_000)
-        }
-        assertTransition(from = SceneA, to = SceneB, progress = 0f)
-    }
-
-    @Test
     fun sceneWithoutSwipesDoesNotConsumeGestures() {
         val buttonTag = "button"
 
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
index 70f2ff80..cb87fe8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/TransitionDslTest.kt
@@ -21,7 +21,6 @@
 import androidx.compose.animation.core.TweenSpec
 import androidx.compose.animation.core.spring
 import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.ui.unit.IntSize
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.compose.animation.scene.TestScenes.SceneA
@@ -29,7 +28,6 @@
 import com.android.compose.animation.scene.TestScenes.SceneC
 import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.transformation.CustomPropertyTransformation
-import com.android.compose.animation.scene.transformation.OverscrollTranslate
 import com.android.compose.animation.scene.transformation.PropertyTransformation
 import com.android.compose.animation.scene.transformation.PropertyTransformationScope
 import com.android.compose.animation.scene.transformation.TransformationMatcher
@@ -308,34 +306,6 @@
     }
 
     @Test
-    fun overscrollSpec() {
-        val transitions = transitions {
-            overscroll(SceneA, Orientation.Vertical) {
-                translate(TestElements.Bar, x = { 1f }, y = { 2f })
-            }
-        }
-
-        val overscrollSpec = transitions.overscrollSpecs.single()
-        val transformation =
-            overscrollSpec.transformationSpec.transformationMatchers.single().factory.create()
-        assertThat(transformation).isInstanceOf(OverscrollTranslate::class.java)
-    }
-
-    @Test
-    fun overscrollSpec_for_overscrollDisabled() {
-        val transitions = transitions { overscrollDisabled(SceneA, Orientation.Vertical) }
-        val overscrollSpec = transitions.overscrollSpecs.single()
-        assertThat(overscrollSpec.transformationSpec.transformationMatchers).isEmpty()
-    }
-
-    @Test
-    fun overscrollSpec_throwIfTransformationsIsEmpty() {
-        assertThrows(IllegalStateException::class.java) {
-            transitions { overscroll(SceneA, Orientation.Vertical) {} }
-        }
-    }
-
-    @Test
     fun transitionIsPassedToBuilder() = runTest {
         var transitionPassedToBuilder: TransitionState.Transition? = null
         val state =
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
index 9a2af64..6db98a8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
@@ -16,9 +16,7 @@
 
 package com.android.compose.animation.scene.subjects
 
-import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.OverlayKey
-import com.android.compose.animation.scene.OverscrollSpec
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.content.state.TransitionState
 import com.google.common.truth.Fact.simpleFact
@@ -156,26 +154,6 @@
     fun hasIsUserInputOngoing(isUserInputOngoing: Boolean) {
         check("isUserInputOngoing").that(actual.isUserInputOngoing).isEqualTo(isUserInputOngoing)
     }
-
-    internal fun hasOverscrollSpec(): OverscrollSpec {
-        check("currentOverscrollSpec").that(actual.currentOverscrollSpec).isNotNull()
-        return actual.currentOverscrollSpec!!
-    }
-
-    fun hasNoOverscrollSpec() {
-        check("currentOverscrollSpec").that(actual.currentOverscrollSpec).isNull()
-    }
-
-    fun hasBouncingContent(content: ContentKey) {
-        val actual = actual
-        if (actual !is TransitionState.DirectionProperties) {
-            failWithActual(simpleFact("expected to be ContentState.HasOverscrollProperties"))
-        }
-
-        check("bouncingContent")
-            .that((actual as TransitionState.DirectionProperties).bouncingContent)
-            .isEqualTo(content)
-    }
 }
 
 class SceneTransitionSubject
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt
new file mode 100644
index 0000000..0da422b
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedElementTransformationTest.kt
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene.transformation
+
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.test.SemanticsNodeInteraction
+import androidx.compose.ui.test.assertPositionInRootIsEqualTo
+import androidx.compose.ui.test.isNotDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.ElementKey
+import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
+import com.android.compose.animation.scene.Scale
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SceneTransitionLayout
+import com.android.compose.animation.scene.SceneTransitions
+import com.android.compose.animation.scene.TestScenes
+import com.android.compose.animation.scene.testNestedTransition
+import com.android.compose.animation.scene.testing.lastAlphaForTesting
+import com.android.compose.animation.scene.testing.lastScaleForTesting
+import com.android.compose.animation.scene.transitions
+import com.android.compose.test.assertSizeIsEqualTo
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NestedElementTransformationTest {
+    @get:Rule val rule = createComposeRule()
+
+    private object Scenes {
+        val NestedSceneA = SceneKey("NestedSceneA")
+        val NestedSceneB = SceneKey("NestedSceneB")
+        val NestedNestedSceneA = SceneKey("NestedNestedSceneA")
+        val NestedNestedSceneB = SceneKey("NestedNestedSceneB")
+    }
+
+    // Variants are named: nestingDepth + sceneNameSuffix
+    private val elementVariant0A =
+        TestElement(ElementKey("0A"), 0.dp, 0.dp, 100.dp, 100.dp, Color.Red)
+    private val elementVariant0B =
+        TestElement(ElementKey("0B"), 100.dp, 100.dp, 20.dp, 20.dp, Color.Cyan)
+    private val elementVariant1A =
+        TestElement(ElementKey("1A"), 40.dp, 80.dp, 60.dp, 20.dp, Color.Blue)
+    private val elementVariant1B =
+        TestElement(ElementKey("1B"), 80.dp, 40.dp, 140.dp, 180.dp, Color.Yellow)
+    private val elementVariant2A =
+        TestElement(ElementKey("2A"), 120.dp, 240.dp, 20.dp, 140.dp, Color.Green)
+    private val elementVariant2B =
+        TestElement(ElementKey("2B"), 200.dp, 320.dp, 40.dp, 70.dp, Color.Magenta)
+
+    private class TestElement(
+        val key: ElementKey,
+        val x: Dp,
+        val y: Dp,
+        val width: Dp,
+        val height: Dp,
+        val color: Color = Color.Black,
+        val alpha: Float = 0.8f,
+    )
+
+    @Composable
+    private fun ContentScope.TestElement(element: TestElement) {
+        Box(Modifier.fillMaxSize()) {
+            Box(
+                Modifier.offset(element.x, element.y)
+                    .element(element.key)
+                    .size(element.width, element.height)
+                    .background(element.color)
+                    .alpha(element.alpha)
+            )
+        }
+    }
+
+    private fun createState(
+        startScene: SceneKey,
+        transitions: SceneTransitions = SceneTransitions.Empty,
+    ): MutableSceneTransitionLayoutState {
+        return rule.runOnUiThread { MutableSceneTransitionLayoutState(startScene, transitions) }
+    }
+
+    private val threeNestedStls:
+        @Composable
+        (states: List<MutableSceneTransitionLayoutState>) -> Unit =
+        { states ->
+            SceneTransitionLayout(states[0]) {
+                scene(TestScenes.SceneA, content = { TestElement(elementVariant0A) })
+                scene(
+                    TestScenes.SceneB,
+                    content = {
+                        Box(Modifier.fillMaxSize()) {
+                            TestElement(elementVariant0B)
+                            NestedSceneTransitionLayout(states[1], modifier = Modifier) {
+                                scene(Scenes.NestedSceneA) {
+                                    Box(Modifier.fillMaxSize()) {
+                                        TestElement(elementVariant1A)
+                                        NestedSceneTransitionLayout(
+                                            state = states[2],
+                                            modifier = Modifier,
+                                        ) {
+                                            scene(Scenes.NestedNestedSceneA) {
+                                                TestElement(elementVariant2A)
+                                            }
+                                            scene(Scenes.NestedNestedSceneB) {
+                                                TestElement(elementVariant2B)
+                                            }
+                                        }
+                                    }
+                                }
+                                scene(Scenes.NestedSceneB) { TestElement(elementVariant1B) }
+                            }
+                        }
+                    },
+                )
+            }
+        }
+
+    @Test
+    fun transitionInNestedNestedStl_transitionsOut() {
+        rule.testNestedTransition(
+            states =
+                listOf(
+                    createState(TestScenes.SceneB),
+                    createState(Scenes.NestedSceneA),
+                    createState(
+                        Scenes.NestedNestedSceneA,
+                        transitions {
+                            from(from = Scenes.NestedNestedSceneA, to = Scenes.NestedNestedSceneB) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 100.dp, y = 50.dp)
+                                scaleSize(elementVariant2A.key, width = 2f, height = 0.5f)
+                                scaleDraw(elementVariant2A.key, scaleX = 4f, scaleY = 0.25f)
+                                fade(elementVariant2A.key)
+                            }
+                        },
+                    ),
+                ),
+            transitionLayout = threeNestedStls,
+            changeState = { it[2].setTargetScene(Scenes.NestedNestedSceneB, this) },
+        ) {
+            before { onElement(elementVariant2A.key).assertElementVariant(elementVariant2A) }
+            atAllFrames(4) {
+                onElement(elementVariant2A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant2A.x, elementVariant2A.x + 100.dp),
+                        interpolate(elementVariant2A.y, elementVariant2A.y + 50.dp),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant2A.width, elementVariant2A.width * 2f),
+                        interpolate(elementVariant2A.height, elementVariant2A.height * 0.5f),
+                    )
+                val semanticNode = onElement(elementVariant2A.key).fetchSemanticsNode()
+                assertThat(semanticNode.lastAlphaForTesting).isEqualTo(interpolate(1f, 0f))
+                assertThat(semanticNode.lastScaleForTesting)
+                    .isEqualTo(interpolate(Scale(1f, 1f), Scale(4f, 0.25f)))
+            }
+            after { onElement(elementVariant2A.key).isNotDisplayed() }
+        }
+    }
+
+    @Test
+    fun transitionInNestedNestedStl_transitionsIn() {
+        rule.testNestedTransition(
+            states =
+                listOf(
+                    createState(TestScenes.SceneB),
+                    createState(Scenes.NestedSceneA),
+                    createState(
+                        Scenes.NestedNestedSceneB,
+                        transitions {
+                            from(from = Scenes.NestedNestedSceneB) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 100.dp, y = 50.dp)
+                                scaleSize(elementVariant2A.key, width = 2f, height = 0.5f)
+                            }
+                        },
+                    ),
+                ),
+            transitionLayout = threeNestedStls,
+            changeState = { it[2].setTargetScene(Scenes.NestedNestedSceneA, this) },
+        ) {
+            before { onElement(elementVariant2A.key).isNotDisplayed() }
+            atAllFrames(4) {
+                onElement(elementVariant2A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant2A.x + 100.dp, elementVariant2A.x),
+                        interpolate(elementVariant2A.y + 50.dp, elementVariant2A.y),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant2A.width * 2f, elementVariant2A.width),
+                        interpolate(elementVariant2A.height * 0.5f, elementVariant2A.height),
+                    )
+            }
+            after { onElement(elementVariant2A.key).assertElementVariant(elementVariant2A) }
+        }
+    }
+
+    @Test
+    fun transitionInNestedStl_elementInNestedNestedStl_transitionsIn() {
+        rule.testNestedTransition(
+            states =
+                listOf(
+                    createState(TestScenes.SceneB),
+                    createState(
+                        Scenes.NestedSceneB,
+                        transitions {
+                            from(from = Scenes.NestedSceneB, to = Scenes.NestedSceneA) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 100.dp, y = 50.dp)
+                                scaleSize(elementVariant2A.key, width = 2f, height = 0.5f)
+                            }
+                        },
+                    ),
+                    createState(Scenes.NestedNestedSceneA),
+                ),
+            transitionLayout = threeNestedStls,
+            changeState = { it[1].setTargetScene(Scenes.NestedSceneA, this) },
+        ) {
+            before { onElement(elementVariant2A.key).isNotDisplayed() }
+            atAllFrames(4) {
+                onElement(elementVariant2A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant2A.x + 100.dp, elementVariant2A.x),
+                        interpolate(elementVariant2A.y + 50.dp, elementVariant2A.y),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant2A.width * 2f, elementVariant2A.width),
+                        interpolate(elementVariant2A.height * 0.5f, elementVariant2A.height),
+                    )
+            }
+            after { onElement(elementVariant2A.key).assertElementVariant(elementVariant2A) }
+        }
+    }
+
+    @Test
+    fun transitionInRootStl_elementsInAllLayers_transitionInAndOut() {
+        rule.testNestedTransition(
+            states =
+                listOf(
+                    createState(
+                        TestScenes.SceneB,
+                        transitions {
+                            to(to = TestScenes.SceneA) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+
+                                // transitions out
+                                translate(elementVariant2A.key, x = 100.dp, y = 50.dp)
+                                scaleSize(elementVariant2A.key, width = 2f, height = 0.5f)
+
+                                // transitions out
+                                translate(elementVariant0B.key, x = 200.dp, y = 20.dp)
+                                scaleSize(elementVariant0B.key, width = 3f, height = 0.2f)
+
+                                // transitions out
+                                translate(elementVariant1A.key, x = 300.dp, y = 10.dp)
+                                scaleSize(elementVariant1A.key, width = 4f, height = 0.1f)
+
+                                // transitions in
+                                translate(elementVariant0A.key, x = 400.dp, y = 40.dp)
+                                scaleSize(elementVariant0A.key, width = 0.5f, height = 2f)
+                            }
+                        },
+                    ),
+                    createState(Scenes.NestedSceneA),
+                    createState(Scenes.NestedNestedSceneA),
+                ),
+            transitionLayout = threeNestedStls,
+            changeState = { it[0].setTargetScene(TestScenes.SceneA, this) },
+        ) {
+            before {
+                onElement(elementVariant2A.key).assertElementVariant(elementVariant2A)
+                onElement(elementVariant0B.key).assertElementVariant(elementVariant0B)
+                onElement(elementVariant1A.key).assertElementVariant(elementVariant1A)
+                onElement(elementVariant0A.key).isNotDisplayed()
+            }
+            atAllFrames(4) {
+                onElement(elementVariant2A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant2A.x, elementVariant2A.x + 100.dp),
+                        interpolate(elementVariant2A.y, elementVariant2A.y + 50.dp),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant2A.width, elementVariant2A.width * 2f),
+                        interpolate(elementVariant2A.height, elementVariant2A.height * 0.5f),
+                    )
+
+                onElement(elementVariant0B.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant0B.x, elementVariant0B.x + 200.dp),
+                        interpolate(elementVariant0B.y, elementVariant0B.y + 20.dp),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant0B.width, elementVariant0B.width * 3f),
+                        interpolate(elementVariant0B.height, elementVariant0B.height * 0.2f),
+                    )
+
+                onElement(elementVariant1A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant1A.x, elementVariant1A.x + 300.dp),
+                        interpolate(elementVariant1A.y, elementVariant1A.y + 10.dp),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant1A.width, elementVariant1A.width * 4f),
+                        interpolate(elementVariant1A.height, elementVariant1A.height * 0.1f),
+                    )
+
+                onElement(elementVariant0A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant0A.x + 400.dp, elementVariant0A.x),
+                        interpolate(elementVariant0A.y + 40.dp, elementVariant0A.y),
+                    )
+                    .assertSizeIsEqualTo(
+                        interpolate(elementVariant0A.width * 0.5f, elementVariant0A.width),
+                        interpolate(elementVariant0A.height * 2f, elementVariant0A.height),
+                    )
+            }
+            after {
+                onElement(elementVariant2A.key).isNotDisplayed()
+                onElement(elementVariant0B.key).isNotDisplayed()
+                onElement(elementVariant1A.key).isNotDisplayed()
+                onElement(elementVariant0A.key).assertElementVariant(elementVariant0A)
+            }
+        }
+    }
+
+    @Test
+    fun transitionInMultipleStls_rootIsTakingControl() {
+        rule.testNestedTransition(
+            states =
+                listOf(
+                    createState(
+                        TestScenes.SceneB,
+                        transitions {
+                            to(to = TestScenes.SceneA) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 100.dp, y = 50.dp)
+                            }
+                        },
+                    ),
+                    createState(
+                        Scenes.NestedSceneA,
+                        transitions {
+                            to(to = Scenes.NestedSceneB) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 200.dp, y = 150.dp)
+                            }
+                        },
+                    ),
+                    createState(
+                        Scenes.NestedNestedSceneA,
+                        transitions {
+                            to(to = Scenes.NestedNestedSceneB) {
+                                spec = tween(16 * 4, easing = LinearEasing)
+                                translate(elementVariant2A.key, x = 300.dp, y = 250.dp)
+                            }
+                        },
+                    ),
+                ),
+            transitionLayout = threeNestedStls,
+            changeState = {
+                it[2].setTargetScene(Scenes.NestedNestedSceneB, this)
+                it[1].setTargetScene(Scenes.NestedSceneB, this)
+                it[0].setTargetScene(TestScenes.SceneA, this)
+            },
+        ) {
+            before { onElement(elementVariant2A.key).assertElementVariant(elementVariant2A) }
+            atAllFrames(4) {
+                onElement(elementVariant2A.key)
+                    .assertPositionInRootIsEqualTo(
+                        interpolate(elementVariant2A.x, elementVariant2A.x + 100.dp),
+                        interpolate(elementVariant2A.y, elementVariant2A.y + 50.dp),
+                    )
+            }
+            after { onElement(elementVariant2A.key).isNotDisplayed() }
+        }
+    }
+
+    private fun SemanticsNodeInteraction.assertElementVariant(variant: TestElement) {
+        assertPositionInRootIsEqualTo(variant.x, variant.y)
+        assertSizeIsEqualTo(variant.width, variant.height)
+    }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedSharedElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedSharedElementTest.kt
index c6ef8cf..d8b7136 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedSharedElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/NestedSharedElementTest.kt
@@ -61,7 +61,7 @@
         val NestedNestedSceneB = SceneKey("NestedNestedSceneB")
     }
 
-    private val elementVariant1 = SharedElement(0.dp, 0.dp, 100.dp, 100.dp, Color.Red)
+    private val elementVariant1 = SharedElement(100.dp, 100.dp, 100.dp, 100.dp, Color.Red)
     private val elementVariant2 = SharedElement(40.dp, 80.dp, 60.dp, 20.dp, Color.Blue)
     private val elementVariant3 = SharedElement(80.dp, 40.dp, 140.dp, 180.dp, Color.Yellow)
     private val elementVariant4 = SharedElement(120.dp, 240.dp, 20.dp, 140.dp, Color.Green)
@@ -223,7 +223,8 @@
                 // In SceneA, Foo leaves to the left edge.
                 translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left, false)
 
-                // We can't reference the element inside the NestedSTL as of today
+                // In NestedSceneA, Foo comes in from the top edge.
+                translate(TestElements.Foo.inScene(Scenes.NestedSceneA), Edge.Top, false)
             },
         ) {
             before { onElement(TestElements.Foo).assertElementVariant(elementVariant1) }
@@ -234,6 +235,11 @@
                         elementVariant1.y,
                     )
                     .assertSizeIsEqualTo(elementVariant1.width, elementVariant1.height)
+                onElement(TestElements.Foo, scene = Scenes.NestedSceneA)
+                    .assertPositionInRootIsEqualTo(
+                        elementVariant2.x,
+                        interpolate(0.dp, elementVariant2.y),
+                    )
             }
             after { onElement(TestElements.Foo).assertElementVariant(elementVariant2) }
         }
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
index 47c10f5..0dd08d9 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/transformation/SharedElementTest.kt
@@ -18,11 +18,13 @@
 
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.size
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.test.assertIsNotDisplayed
 import androidx.compose.ui.test.assertPositionInRootIsEqualTo
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -47,11 +49,21 @@
         rule.testTransition(
             fromSceneContent = {
                 // Foo is at (10, 50) with a size of (20, 80).
-                Box(Modifier.offset(10.dp, 50.dp).element(TestElements.Foo).size(20.dp, 80.dp))
+                Box(
+                    Modifier.offset(10.dp, 50.dp)
+                        .element(TestElements.Foo)
+                        .size(20.dp, 80.dp)
+                        .background(Color.Red)
+                )
             },
             toSceneContent = {
                 // Foo is at (50, 70) with a size of (10, 40).
-                Box(Modifier.offset(50.dp, 70.dp).element(TestElements.Foo).size(10.dp, 40.dp))
+                Box(
+                    Modifier.offset(50.dp, 70.dp)
+                        .element(TestElements.Foo)
+                        .size(10.dp, 40.dp)
+                        .background(Color.Blue)
+                )
             },
             transition = {
                 spec = tween(16 * 4, easing = LinearEasing)
@@ -88,13 +100,23 @@
             fromSceneContent = {
                 Box(Modifier.fillMaxSize()) {
                     // Foo is at (10, 50).
-                    Box(Modifier.offset(10.dp, 50.dp).element(TestElements.Foo))
+                    Box(
+                        Modifier.offset(10.dp, 50.dp)
+                            .element(TestElements.Foo)
+                            .size(20.dp)
+                            .background(Color.Red)
+                    )
                 }
             },
             toSceneContent = {
                 Box(Modifier.fillMaxSize()) {
                     // Foo is at (50, 60).
-                    Box(Modifier.offset(50.dp, 60.dp).element(TestElements.Foo))
+                    Box(
+                        Modifier.offset(50.dp, 60.dp)
+                            .element(TestElements.Foo)
+                            .size(20.dp)
+                            .background(Color.Blue)
+                    )
                 }
             },
             transition = {
@@ -104,7 +126,11 @@
                 sharedElement(TestElements.Foo, enabled = false)
 
                 // In SceneA, Foo leaves to the left edge.
-                translate(TestElements.Foo.inScene(TestScenes.SceneA), Edge.Left)
+                translate(
+                    TestElements.Foo.inScene(TestScenes.SceneA),
+                    Edge.Left,
+                    startsOutsideLayoutBounds = false,
+                )
 
                 // In SceneB, Foo comes from the bottom edge.
                 translate(TestElements.Foo.inScene(TestScenes.SceneB), Edge.Bottom)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
index c8fb2cb..53bb14f 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnectionTest.kt
@@ -19,7 +19,6 @@
 import androidx.compose.foundation.gestures.FlingBehavior
 import androidx.compose.foundation.gestures.ScrollScope
 import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
@@ -48,15 +47,6 @@
             flingBehavior = customFlingBehavior,
         )
 
-    private fun NestedScrollConnection.scroll(
-        available: Offset,
-        consumedByScroll: Offset = Offset.Zero,
-    ) {
-        val consumedByPreScroll = onPreScroll(available = available, source = scrollSource)
-        val consumed = consumedByPreScroll + consumedByScroll
-        onPostScroll(consumed = consumed, available = available - consumed, source = scrollSource)
-    }
-
     @Test
     fun onScrollUp_consumeHeightFirst() {
         val scrollConnection = buildScrollConnection(heightRange = 0f..2f)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/Selectors.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/Selectors.kt
deleted file mode 100644
index d6f64bf..0000000
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/Selectors.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.compose.test
-
-import androidx.compose.ui.test.SemanticsNodeInteraction
-import androidx.compose.ui.test.SemanticsNodeInteractionCollection
-
-/** Assert [assert] on each element of [this] [SemanticsNodeInteractionCollection]. */
-fun SemanticsNodeInteractionCollection.onEach(assert: SemanticsNodeInteraction.() -> Unit) {
-    for (i in 0 until this.fetchSemanticsNodes().size) {
-        get(i).assert()
-    }
-}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
index 6015479..b9d01c2 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
@@ -16,12 +16,9 @@
 
 package com.android.compose.test
 
-import androidx.compose.foundation.gestures.Orientation
-import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.OverlayKey
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.content.state.TransitionState.Transition
 import kotlinx.coroutines.CompletableDeferred
 
@@ -63,15 +60,10 @@
     interruptionProgress: () -> Float = { 0f },
     isInitiatedByUserInput: Boolean = false,
     isUserInputOngoing: Boolean = false,
-    isUpOrLeft: Boolean = false,
-    bouncingContent: ContentKey? = null,
-    orientation: Orientation = Orientation.Horizontal,
     onFreezeAndAnimate: ((TestOverlayTransition) -> Unit)? = null,
     replacedTransition: Transition? = null,
 ): TestOverlayTransition {
-    return object :
-        TestOverlayTransition(fromScene, overlay, replacedTransition),
-        TransitionState.DirectionProperties {
+    return object : TestOverlayTransition(fromScene, overlay, replacedTransition) {
         override val isEffectivelyShown: Boolean
             get() = isEffectivelyShown()
 
@@ -92,10 +84,6 @@
 
         override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
         override val isUserInputOngoing: Boolean = isUserInputOngoing
-        override val isUpOrLeft: Boolean = isUpOrLeft
-        override val bouncingContent: ContentKey? = bouncingContent
-        override val orientation: Orientation = orientation
-        override val absoluteDistance = 0f
 
         override fun freezeAndAnimateToCurrentState() {
             if (onFreezeAndAnimate != null) {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt
index bd2118d..983c429 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt
@@ -16,11 +16,8 @@
 
 package com.android.compose.test
 
-import androidx.compose.foundation.gestures.Orientation
-import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.OverlayKey
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.content.state.TransitionState.Transition
 import kotlinx.coroutines.CompletableDeferred
 
@@ -60,15 +57,10 @@
     interruptionProgress: () -> Float = { 0f },
     isInitiatedByUserInput: Boolean = false,
     isUserInputOngoing: Boolean = false,
-    isUpOrLeft: Boolean = false,
-    bouncingContent: ContentKey? = null,
-    orientation: Orientation = Orientation.Horizontal,
     onFreezeAndAnimate: ((TestReplaceOverlayTransition) -> Unit)? = null,
     replacedTransition: Transition? = null,
 ): TestReplaceOverlayTransition {
-    return object :
-        TestReplaceOverlayTransition(from, to, replacedTransition),
-        TransitionState.DirectionProperties {
+    return object : TestReplaceOverlayTransition(from, to, replacedTransition) {
         override val effectivelyShownOverlay: OverlayKey
             get() = effectivelyShownOverlay()
 
@@ -89,10 +81,6 @@
 
         override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
         override val isUserInputOngoing: Boolean = isUserInputOngoing
-        override val isUpOrLeft: Boolean = isUpOrLeft
-        override val bouncingContent: ContentKey? = bouncingContent
-        override val orientation: Orientation = orientation
-        override val absoluteDistance = 0f
 
         override fun freezeAndAnimateToCurrentState() {
             if (onFreezeAndAnimate != null) {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
index 1d27e3a..d11951e 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
@@ -16,11 +16,8 @@
 
 package com.android.compose.test
 
-import androidx.compose.foundation.gestures.Orientation
-import com.android.compose.animation.scene.ContentKey
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.TransitionState
 import com.android.compose.animation.scene.content.state.TransitionState.Transition
 import kotlinx.coroutines.CompletableDeferred
 
@@ -55,14 +52,10 @@
     interruptionProgress: () -> Float = { 0f },
     isInitiatedByUserInput: Boolean = false,
     isUserInputOngoing: Boolean = false,
-    isUpOrLeft: Boolean = false,
-    bouncingContent: ContentKey? = null,
-    orientation: Orientation = Orientation.Horizontal,
     onFreezeAndAnimate: ((TestSceneTransition) -> Unit)? = null,
     replacedTransition: Transition? = null,
 ): TestSceneTransition {
-    return object :
-        TestSceneTransition(from, to, replacedTransition), TransitionState.DirectionProperties {
+    return object : TestSceneTransition(from, to, replacedTransition) {
         override val currentScene: SceneKey
             get() = current()
 
@@ -83,10 +76,6 @@
 
         override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
         override val isUserInputOngoing: Boolean = isUserInputOngoing
-        override val isUpOrLeft: Boolean = isUpOrLeft
-        override val bouncingContent: ContentKey? = bouncingContent
-        override val orientation: Orientation = orientation
-        override val absoluteDistance = 0f
 
         override fun freezeAndAnimateToCurrentState() {
             if (onFreezeAndAnimate != null) {
diff --git a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
index 124b61e..bc160fc 100644
--- a/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/utils/src/com/android/compose/animation/scene/TestTransition.kt
@@ -25,6 +25,7 @@
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.semantics.SemanticsNode
 import androidx.compose.ui.test.SemanticsNodeInteraction
 import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
@@ -63,6 +64,9 @@
      * Important: [timestamp] must be a multiple of 16 (the duration of a frame on the JVM/Android).
      * There is no intermediary state between `t` and `t + 16` , so testing transitions outside of
      * `t = 0`, `t = 16`, `t = 32`, etc does not make sense.
+     *
+     * @param builder the builder can run assertions and is passed the CoroutineScope such that the
+     *   test can start transitions at any desired point in time.
      */
     fun at(timestamp: Long, builder: TransitionTestAssertionScope.() -> Unit)
 
@@ -85,7 +89,7 @@
 }
 
 @TransitionTestDsl
-interface TransitionTestAssertionScope {
+interface TransitionTestAssertionScope : CoroutineScope {
     /**
      * Assert on [element].
      *
@@ -312,6 +316,20 @@
     )
 }
 
+fun ComposeContentTestRule.testNestedTransition(
+    states: List<MutableSceneTransitionLayoutState>,
+    changeState: CoroutineScope.(states: List<MutableSceneTransitionLayoutState>) -> Unit,
+    transitionLayout: @Composable (states: List<MutableSceneTransitionLayoutState>) -> Unit,
+    builder: TransitionTestBuilder.() -> Unit,
+) {
+    testTransition(
+        state = states[0],
+        changeState = { changeState(states) },
+        transitionLayout = { transitionLayout(states) },
+        builder = builder,
+    )
+}
+
 /** Test the transition from [state] to [to]. */
 fun ComposeContentTestRule.testTransition(
     state: MutableSceneTransitionLayoutState,
@@ -319,9 +337,15 @@
     transitionLayout: @Composable (state: MutableSceneTransitionLayoutState) -> Unit,
     builder: TransitionTestBuilder.() -> Unit,
 ) {
-    val test = transitionTest(builder)
+    lateinit var coroutineScope: CoroutineScope
+    setContent {
+        coroutineScope = rememberCoroutineScope()
+        transitionLayout(state)
+    }
+
     val assertionScope =
-        object : AutoTransitionTestAssertionScope {
+        object : AutoTransitionTestAssertionScope, CoroutineScope by coroutineScope {
+
             var progress = 0f
 
             override fun onElement(
@@ -338,6 +362,16 @@
                     from is Int && to is Int -> lerp(from, to, progress)
                     from is Long && to is Long -> lerp(from, to, progress)
                     from is Dp && to is Dp -> lerp(from, to, progress)
+                    from is Scale && to is Scale ->
+                        Scale(
+                            lerp(from.scaleX, to.scaleX, progress),
+                            lerp(from.scaleY, to.scaleY, progress),
+                            interpolate(from.pivot, to.pivot),
+                        )
+
+                    from is Offset && to is Offset ->
+                        Offset(lerp(from.x, to.x, progress), lerp(from.y, to.y, progress))
+
                     else ->
                         throw UnsupportedOperationException(
                             "Interpolation not supported for this type"
@@ -347,14 +381,9 @@
             }
         }
 
-    lateinit var coroutineScope: CoroutineScope
-    setContent {
-        coroutineScope = rememberCoroutineScope()
-        transitionLayout(state)
-    }
-
     // Wait for the UI to be idle then test the before state.
     waitForIdle()
+    val test = transitionTest(builder)
     test.before(assertionScope)
 
     // Manually advance the clock to the start of the animation.
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 801a2d6..b76656d 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -71,7 +71,6 @@
         }
 
     var hasCustomPositionUpdatedAnimation: Boolean = false
-    var migratedClocks: Boolean = false
 
     private val time = Calendar.getInstance()
 
@@ -228,11 +227,7 @@
     override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
         logger.d("onMeasure")
 
-        if (
-            migratedClocks &&
-                !isSingleLineInternal &&
-                MeasureSpec.getMode(heightMeasureSpec) == EXACTLY
-        ) {
+        if (!isSingleLineInternal && MeasureSpec.getMode(heightMeasureSpec) == EXACTLY) {
             // Call straight into TextView.setTextSize to avoid setting lastUnconstrainedTextSize
             val size = min(lastUnconstrainedTextSize, MeasureSpec.getSize(heightMeasureSpec) / 2F)
             super.setTextSize(COMPLEX_UNIT_PX, size)
@@ -248,7 +243,7 @@
                     }
             }
 
-        if (migratedClocks && hasCustomPositionUpdatedAnimation) {
+        if (hasCustomPositionUpdatedAnimation) {
             // Expand width to avoid clock being clipped during stepping animation
             val targetWidth = measuredWidth + MeasureSpec.getSize(widthMeasureSpec) / 2
 
@@ -582,12 +577,10 @@
     }
 
     override fun onRtlPropertiesChanged(layoutDirection: Int) {
-        if (migratedClocks) {
-            if (layoutDirection == LAYOUT_DIRECTION_RTL) {
-                textAlignment = TEXT_ALIGNMENT_TEXT_END
-            } else {
-                textAlignment = TEXT_ALIGNMENT_TEXT_START
-            }
+        if (layoutDirection == LAYOUT_DIRECTION_RTL) {
+            textAlignment = TEXT_ALIGNMENT_TEXT_END
+        } else {
+            textAlignment = TEXT_ALIGNMENT_TEXT_START
         }
         super.onRtlPropertiesChanged(layoutDirection)
     }
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index ad9eba8..74d595c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -20,7 +20,6 @@
 import android.icu.text.NumberFormat
 import android.util.TypedValue
 import android.view.LayoutInflater
-import android.view.View
 import android.widget.FrameLayout
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.customization.R
@@ -55,7 +54,6 @@
     private val layoutInflater: LayoutInflater,
     private val resources: Resources,
     private val settings: ClockSettings?,
-    private val migratedClocks: Boolean = false,
     messageBuffers: ClockMessageBuffers? = null,
 ) : ClockController {
     override val smallClock: DefaultClockFaceController
@@ -67,7 +65,6 @@
     private val burmeseLineSpacing =
         resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale_burmese)
     private val defaultLineSpacing = resources.getFloat(R.dimen.keyguard_clock_line_spacing_scale)
-    protected var onSecondaryDisplay: Boolean = false
 
     override val events: DefaultClockEvents
     override val config: ClockConfig by lazy {
@@ -175,10 +172,7 @@
                     recomputePadding(targetRegion)
                 }
 
-                override fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) {
-                    this@DefaultClockController.onSecondaryDisplay = onSecondaryDisplay
-                    recomputePadding(null)
-                }
+                override fun onSecondaryDisplayChanged(onSecondaryDisplay: Boolean) {}
             }
 
         open fun recomputePadding(targetRegion: Rect?) {}
@@ -197,32 +191,11 @@
         override val config = ClockFaceConfig(hasCustomPositionUpdatedAnimation = true)
 
         init {
-            view.migratedClocks = migratedClocks
             view.hasCustomPositionUpdatedAnimation = true
             animations = LargeClockAnimations(view, 0f, 0f)
         }
 
-        override fun recomputePadding(targetRegion: Rect?) {
-            if (migratedClocks) {
-                return
-            }
-            // We center the view within the targetRegion instead of within the parent
-            // view by computing the difference and adding that to the padding.
-            val lp = view.getLayoutParams() as FrameLayout.LayoutParams
-            lp.topMargin =
-                if (onSecondaryDisplay) {
-                    // On the secondary display we don't want any additional top/bottom margin.
-                    0
-                } else {
-                    val parent = view.parent
-                    val yDiff =
-                        if (targetRegion != null && parent is View && parent.isLaidOut())
-                            targetRegion.centerY() - parent.height / 2f
-                        else 0f
-                    (-0.5f * view.bottom + yDiff).toInt()
-                }
-            view.setLayoutParams(lp)
-        }
+        override fun recomputePadding(targetRegion: Rect?) {}
 
         /** See documentation at [AnimatableClockView.offsetGlyphsForStepClockAnimation]. */
         fun offsetGlyphsForStepClockAnimation(fromLeft: Int, direction: Int, fraction: Float) {
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index e898725..c73e1c3 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -47,7 +47,6 @@
     val ctx: Context,
     val layoutInflater: LayoutInflater,
     val resources: Resources,
-    private val migratedClocks: Boolean = false,
     private val isClockReactiveVariantsEnabled: Boolean = false,
 ) : ClockProvider {
     private var messageBuffers: ClockMessageBuffers? = null
@@ -83,14 +82,7 @@
                 FLEX_DESIGN,
             )
         } else {
-            DefaultClockController(
-                ctx,
-                layoutInflater,
-                resources,
-                settings,
-                migratedClocks,
-                messageBuffers,
-            )
+            DefaultClockController(ctx, layoutInflater, resources, settings, messageBuffers)
         }
     }
 
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
index 21d41ae..4a47f1b 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt
@@ -140,8 +140,8 @@
         }
 
         /**
-         * targetRegion passed to all customized clock applies counter translationY of
-         * KeyguardStatusView and keyguard_large_clock_top_margin from default clock
+         * targetRegion passed to all customized clock applies counter translationY of Keyguard and
+         * keyguard_large_clock_top_margin from default clock
          */
         override fun onTargetRegionChanged(targetRegion: Rect?) {
             // When a clock needs to be aligned with screen, like weather clock
diff --git a/packages/SystemUI/docs/clock-plugins.md b/packages/SystemUI/docs/clock-plugins.md
index fee82df..813038e 100644
--- a/packages/SystemUI/docs/clock-plugins.md
+++ b/packages/SystemUI/docs/clock-plugins.md
@@ -43,12 +43,6 @@
 SystemUI event dispatchers to the clock controllers. It maintains a set of event listeners, but
 otherwise attempts to do as little work as possible. It does maintain some state where necessary.
 
-[KeyguardClockSwitchController](../src/com/android/keyguard/KeyguardClockSwitchController.java) is
-the primary controller for the [KeyguardClockSwitch](../src/com/android/keyguard/KeyguardClockSwitch.java),
-which serves as the view parent within SystemUI. Together they ensure the correct clock (either
-large or small) is shown, handle animation between clock sizes, and control some sizing/layout
-parameters for the clocks.
-
 ### Creating a custom clock
 In order to create a custom clock, a partner must:
  - Write an implementation of ClockProviderPlugin and the subinterfaces relevant to your use-case.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
deleted file mode 100644
index b937db6..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.keyguard;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.text.TextUtils;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.TextView;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.res.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class KeyguardClockAccessibilityDelegateTest extends SysuiTestCase {
-
-    private TextView mView;
-    private String m12HoursFormat;
-    private String m24HoursFormat;
-
-    @Before
-    public void setUp() throws Exception {
-        m12HoursFormat = mContext.getString(R.string.keyguard_widget_12_hours_format);
-        m24HoursFormat = mContext.getString(R.string.keyguard_widget_24_hours_format);
-
-        mView = new TextView(mContext);
-        mView.setText(m12HoursFormat);
-        mView.setContentDescription(m12HoursFormat);
-        mView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
-    }
-
-    @Test
-    public void onInitializeAccessibilityEvent_producesNonEmptyAsciiContentDesc() throws Exception {
-        AccessibilityEvent ev = AccessibilityEvent.obtain();
-        mView.onInitializeAccessibilityEvent(ev);
-
-        assertFalse(TextUtils.isEmpty(ev.getContentDescription()));
-        assertTrue(isAscii(ev.getContentDescription()));
-    }
-
-    @Test
-    public void onPopulateAccessibilityEvent_producesNonEmptyAsciiText() throws Exception {
-        AccessibilityEvent ev = AccessibilityEvent.obtain();
-        mView.onPopulateAccessibilityEvent(ev);
-
-        assertFalse(isEmpty(ev.getText()));
-        assertTrue(isAscii(ev.getText()));
-    }
-
-    @Test
-    public void onInitializeAccessibilityNodeInfo_producesNonEmptyAsciiText() throws Exception {
-        AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
-        // Usually done in View.onInitializeAccessibilityNodeInfoInternal, but only when attached.
-        info.setContentDescription(mView.getContentDescription());
-        mView.onInitializeAccessibilityNodeInfo(info);
-
-        assertFalse(TextUtils.isEmpty(info.getText()));
-        assertTrue(isAscii(info.getText()));
-
-        assertFalse(TextUtils.isEmpty(info.getContentDescription()));
-        assertTrue(isAscii(info.getContentDescription()));
-    }
-
-    @Test
-    public void isNeeded_returnsTrueIfDateFormatsContainNonAscii() {
-        if (!isAscii(m12HoursFormat) || !isAscii(m24HoursFormat)) {
-            assertTrue(KeyguardClockAccessibilityDelegate.isNeeded(mContext));
-        }
-    }
-
-    @Test
-    public void isNeeded_returnsWhetherFancyColonExists() {
-        boolean hasFancyColon = !TextUtils.isEmpty(mContext.getString(
-                R.string.keyguard_fancy_colon));
-
-        assertEquals(hasFancyColon, KeyguardClockAccessibilityDelegate.isNeeded(mContext));
-    }
-
-    private boolean isAscii(CharSequence text) {
-        return text.chars().allMatch((i) -> i < 128);
-    }
-
-    private boolean isAscii(List<CharSequence> texts) {
-        return texts.stream().allMatch(this::isAscii);
-    }
-
-    private boolean isEmpty(List<CharSequence> texts) {
-        return texts.stream().allMatch(TextUtils::isEmpty);
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardDisplayManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardDisplayManagerTest.kt
index 85bdf92..cea1e96 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardDisplayManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardDisplayManagerTest.kt
@@ -163,6 +163,16 @@
     }
 
     @Test
+    fun testShow_rearDisplayOuterDefaultActive_occluded() {
+        displayTracker.allDisplays = arrayOf(defaultDisplay, secondaryDisplay)
+
+        whenever(deviceStateHelper.isRearDisplayOuterDefaultActive(secondaryDisplay))
+            .thenReturn(true)
+        whenever(keyguardStateController.isOccluded).thenReturn(true)
+        verify(presentationFactory, never()).create(eq(secondaryDisplay))
+    }
+
+    @Test
     fun testShow_presentationCreated() {
         displayTracker.allDisplays = arrayOf(defaultDisplay, secondaryDisplay)
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
index 8b5372a..9d10011 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSliceViewControllerTest.java
@@ -17,7 +17,6 @@
 
 import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -36,7 +35,6 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.FakeDisplayTracker;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.tuner.TunerService;
 
 import org.junit.After;
 import org.junit.Before;
@@ -53,8 +51,6 @@
     @Mock
     private KeyguardSliceView mView;
     @Mock
-    private TunerService mTunerService;
-    @Mock
     private ConfigurationController mConfigurationController;
     @Mock
     private ActivityStarter mActivityStarter;
@@ -74,7 +70,7 @@
         when(mView.isAttachedToWindow()).thenReturn(true);
         when(mView.getContext()).thenReturn(mContext);
         mController = new KeyguardSliceViewController(mHandler, mBgHandler, mView,
-                mActivityStarter, mConfigurationController, mTunerService, mDumpManager,
+                mActivityStarter, mConfigurationController, mDumpManager,
                 mDisplayTracker);
         mController.setupUri(KeyguardSliceProvider.KEYGUARD_SLICE_URI);
     }
@@ -101,7 +97,6 @@
         assumeFalse(isWatch());
 
         mController.init();
-        verify(mTunerService).addTunable(any(TunerService.Tunable.class), anyString());
         verify(mConfigurationController).addCallback(
                 any(ConfigurationController.ConfigurationListener.class));
     }
@@ -120,7 +115,6 @@
 
         attachListenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
 
-        verify(mTunerService).removeTunable(any(TunerService.Tunable.class));
         verify(mConfigurationController).removeCallback(
                 any(ConfigurationController.ConfigurationListener.class));
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
deleted file mode 100644
index 64e4996..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.android.keyguard
-
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@RunWithLooper(setAsMainLooper = true)
-class KeyguardStatusAreaViewTest : SysuiTestCase() {
-
-    private lateinit var view: KeyguardStatusAreaView
-
-    @Before
-    fun setUp() {
-        view = KeyguardStatusAreaView(context)
-    }
-
-    @Test
-    fun checkTranslationX_AddedTotals() {
-        view.translateXFromClockDesign = 10f
-        assertEquals(10f, view.translationX)
-
-        view.translateXFromAod = 20f
-        assertEquals(30f, view.translationX)
-
-        view.translateXFromUnfold = 30f
-        assertEquals(60f, view.translationX)
-    }
-
-    @Test
-    fun checkTranslationY_AddedTotals() {
-        view.translateYFromClockSize = 10f
-        assertEquals(10f, view.translationY)
-
-        view.translateYFromClockDesign = 20f
-        assertEquals(30f, view.translationY)
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
deleted file mode 100644
index 2b4fc5b..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
-
-import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
-import com.android.systemui.kosmos.KosmosJavaAdapter;
-import com.android.systemui.power.data.repository.FakePowerRepository;
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-
-import org.junit.Before;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-public class KeyguardStatusViewControllerBaseTest extends SysuiTestCase {
-
-    private KosmosJavaAdapter mKosmos;
-    @Mock protected KeyguardStatusView mKeyguardStatusView;
-
-    @Mock protected KeyguardSliceViewController mKeyguardSliceViewController;
-    @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
-    @Mock protected KeyguardStateController mKeyguardStateController;
-    @Mock protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    @Mock protected ConfigurationController mConfigurationController;
-    @Mock protected DozeParameters mDozeParameters;
-    @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
-    @Mock protected KeyguardLogger mKeyguardLogger;
-    @Mock protected KeyguardStatusViewController mControllerMock;
-    @Mock protected ViewTreeObserver mViewTreeObserver;
-    protected FakeKeyguardRepository mFakeKeyguardRepository;
-    protected FakePowerRepository mFakePowerRepository;
-
-    protected KeyguardStatusViewController mController;
-
-    @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
-    @Mock protected FrameLayout mMediaHostContainer;
-    @Mock protected KeyguardStatusAreaView mKeyguardStatusAreaView;
-
-    @Before
-    public void setup() {
-        mKosmos = new KosmosJavaAdapter(this);
-        MockitoAnnotations.initMocks(this);
-
-        KeyguardInteractorFactory.WithDependencies deps = KeyguardInteractorFactory.create();
-        mFakeKeyguardRepository = deps.getRepository();
-        mFakePowerRepository = new FakePowerRepository();
-
-        mController = new KeyguardStatusViewController(
-                mKeyguardStatusView,
-                mKeyguardSliceViewController,
-                mKeyguardClockSwitchController,
-                mKeyguardStateController,
-                mKeyguardUpdateMonitor,
-                mConfigurationController,
-                mDozeParameters,
-                mScreenOffAnimationController,
-                mKeyguardLogger,
-                mKosmos.getInteractionJankMonitor(),
-                deps.getKeyguardInteractor(),
-                PowerInteractorFactory.create(
-                        mFakePowerRepository
-                ).getPowerInteractor()) {
-                    @Override
-                    void setProperty(
-                            AnimatableProperty property,
-                            float value,
-                            boolean animate) {
-                        // Route into the mock version for verification
-                        mControllerMock.setProperty(property, value, animate);
-                    }
-                };
-
-        when(mKeyguardStatusView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
-        when(mKeyguardClockSwitchController.getView()).thenReturn(mKeyguardClockSwitch);
-        when(mKeyguardStatusView.findViewById(R.id.keyguard_status_area))
-                .thenReturn(mKeyguardStatusAreaView);
-    }
-
-    protected void givenViewAttached() {
-        ArgumentCaptor<View.OnAttachStateChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
-        verify(mKeyguardStatusView, atLeast(1)).addOnAttachStateChangeListener(captor.capture());
-
-        for (View.OnAttachStateChangeListener listener : captor.getAllValues()) {
-            listener.onViewAttachedToWindow(mKeyguardStatusView);
-        }
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt
deleted file mode 100644
index c29439d..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewControllerWithCoroutinesTest.kt
+++ /dev/null
@@ -1,69 +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.keyguard
-
-import android.testing.TestableLooper
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.power.shared.model.ScreenPowerState
-import kotlinx.coroutines.cancelChildren
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-
-@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class KeyguardStatusViewControllerWithCoroutinesTest : KeyguardStatusViewControllerBaseTest() {
-
-    @Test
-    fun dozeTimeTickUpdatesSlices() = runTest {
-        mController.startCoroutines(coroutineContext)
-        givenViewAttached()
-        runCurrent()
-        clearInvocations(mKeyguardSliceViewController)
-
-        mFakeKeyguardRepository.dozeTimeTick()
-        runCurrent()
-        verify(mKeyguardSliceViewController).refresh()
-
-        coroutineContext.cancelChildren()
-    }
-
-    @Test
-    fun onScreenTurningOnUpdatesSlices() = runTest {
-        mController.startCoroutines(coroutineContext)
-        givenViewAttached()
-        runCurrent()
-        clearInvocations(mKeyguardSliceViewController)
-
-        mFakePowerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
-        runCurrent()
-        verify(mKeyguardSliceViewController, never()).refresh()
-
-        // Should only be called during a 'turning on' event
-        mFakePowerRepository.setScreenPowerState(ScreenPowerState.SCREEN_TURNING_ON)
-        runCurrent()
-        verify(mKeyguardSliceViewController).refresh()
-
-        coroutineContext.cancelChildren()
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewTest.kt
deleted file mode 100644
index 16d2f02..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.android.keyguard
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import android.testing.TestableLooper.RunWithLooper
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import com.android.systemui.res.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.children
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@RunWithLooper(setAsMainLooper = true)
-class KeyguardStatusViewTest : SysuiTestCase() {
-
-    private lateinit var keyguardStatusView: KeyguardStatusView
-    private val mediaView: View
-        get() = keyguardStatusView.requireViewById(R.id.status_view_media_container)
-    private val statusViewContainer: ViewGroup
-        get() = keyguardStatusView.requireViewById(R.id.status_view_container)
-    private val childrenExcludingMedia
-        get() = statusViewContainer.children.filter { it != mediaView }
-
-    @Before
-    fun setUp() {
-        keyguardStatusView =
-            LayoutInflater.from(context).inflate(R.layout.keyguard_status_view, /* root= */ null)
-                as KeyguardStatusView
-    }
-
-    @Test
-    fun setChildrenTranslationYExcludingMediaView_mediaViewIsNotTranslated() {
-        val translationY = 1234f
-
-        keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */ true)
-
-        assertThat(mediaView.translationY).isEqualTo(0)
-
-        childrenExcludingMedia.forEach { assertThat(it.translationY).isEqualTo(translationY) }
-    }
-
-    @Test
-    fun setChildrenTranslationYIncludeMediaView() {
-        val translationY = 1234f
-
-        keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */ false)
-
-        statusViewContainer.children.forEach { assertThat(it.translationY).isEqualTo(translationY) }
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
deleted file mode 100644
index c7d11ef..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
+++ /dev/null
@@ -1,90 +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.keyguard
-
-import android.animation.Animator
-import android.transition.TransitionValues
-import android.view.View
-import android.view.ViewGroup
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardStatusViewController.SplitShadeTransitionAdapter
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SplitShadeTransitionAdapterTest : SysuiTestCase() {
-
-    @Mock private lateinit var KeyguardClockSwitchController: KeyguardClockSwitchController
-
-    private lateinit var adapter: SplitShadeTransitionAdapter
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        adapter = SplitShadeTransitionAdapter(KeyguardClockSwitchController)
-    }
-
-    @Test
-    fun createAnimator_nullStartValues_returnsNull() {
-        val endValues = createEndValues()
-
-        val animator = adapter.createAnimator(startValues = null, endValues = endValues)
-
-        assertThat(animator).isNull()
-    }
-
-    @Test
-    fun createAnimator_nullEndValues_returnsNull() {
-        val animator = adapter.createAnimator(startValues = createStartValues(), endValues = null)
-
-        assertThat(animator).isNull()
-    }
-
-    @Test
-    fun createAnimator_nonNullStartAndEndValues_returnsAnimator() {
-        val animator =
-            adapter.createAnimator(startValues = createStartValues(), endValues = createEndValues())
-
-        assertThat(animator).isNotNull()
-    }
-
-    private fun createStartValues() =
-        TransitionValues().also { values ->
-            values.view = View(context)
-            adapter.captureStartValues(values)
-        }
-
-    private fun createEndValues() =
-        TransitionValues().also { values ->
-            values.view = View(context)
-            adapter.captureEndValues(values)
-        }
-}
-
-private fun SplitShadeTransitionAdapter.createAnimator(
-    startValues: TransitionValues?,
-    endValues: TransitionValues?
-): Animator? {
-    return createAnimator(/* sceneRoot= */ mock(), startValues, endValues)
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayoutTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayoutTest.java
new file mode 100644
index 0000000..455329f
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayoutTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
+import static com.android.systemui.accessibility.hearingaid.AmbientVolumeLayout.ROTATION_COLLAPSED;
+import static com.android.systemui.accessibility.hearingaid.AmbientVolumeLayout.ROTATION_EXPANDED;
+import static com.android.systemui.accessibility.hearingaid.AmbientVolumeLayout.SIDE_UNIFIED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.util.ArrayMap;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.bluetooth.AmbientVolumeUi;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.Map;
+
+/** Tests for {@link AmbientVolumeLayout}. */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AmbientVolumeLayoutTest extends SysuiTestCase {
+
+    private static final int TEST_LEFT_VOLUME_LEVEL = 1;
+    private static final int TEST_RIGHT_VOLUME_LEVEL = 2;
+    private static final int TEST_UNIFIED_VOLUME_LEVEL = 3;
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    private Context mContext = ApplicationProvider.getApplicationContext();
+    @Mock
+    private AmbientVolumeUi.AmbientVolumeUiListener mListener;
+
+    private AmbientVolumeLayout mLayout;
+    private ImageView mExpandIcon;
+    private ImageView mVolumeIcon;
+    private final Map<Integer, BluetoothDevice> mSideToDeviceMap = new ArrayMap<>();
+
+    @Before
+    public void setUp() {
+        mLayout = new AmbientVolumeLayout(mContext);
+        mLayout.setListener(mListener);
+        mLayout.setExpandable(true);
+        mLayout.setMutable(true);
+
+        prepareDevices();
+        mLayout.setupSliders(mSideToDeviceMap);
+        mLayout.getSliders().forEach((side, slider) -> {
+            slider.setMin(0);
+            slider.setMax(4);
+            if (side == SIDE_LEFT) {
+                slider.setValue(TEST_LEFT_VOLUME_LEVEL);
+            } else if (side == SIDE_RIGHT) {
+                slider.setValue(TEST_RIGHT_VOLUME_LEVEL);
+            } else if (side == SIDE_UNIFIED) {
+                slider.setValue(TEST_UNIFIED_VOLUME_LEVEL);
+            }
+        });
+
+        mExpandIcon = mLayout.getExpandIcon();
+        mVolumeIcon = mLayout.getVolumeIcon();
+    }
+
+    @Test
+    public void setExpandable_expandable_expandIconVisible() {
+        mLayout.setExpandable(true);
+
+        assertThat(mExpandIcon.getVisibility()).isEqualTo(VISIBLE);
+    }
+
+    @Test
+    public void setExpandable_notExpandable_expandIconGone() {
+        mLayout.setExpandable(false);
+
+        assertThat(mExpandIcon.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void setExpanded_expanded_assertControlUiCorrect() {
+        mLayout.setExpanded(true);
+
+        assertControlUiCorrect();
+    }
+
+    @Test
+    public void setExpanded_notExpanded_assertControlUiCorrect() {
+        mLayout.setExpanded(false);
+
+        assertControlUiCorrect();
+    }
+
+    @Test
+    public void setMutable_mutable_clickOnMuteIconChangeMuteState() {
+        mLayout.setMutable(true);
+        mLayout.setMuted(false);
+
+        mVolumeIcon.callOnClick();
+
+        assertThat(mLayout.isMuted()).isTrue();
+    }
+
+    @Test
+    public void setMutable_notMutable_clickOnMuteIconWontChangeMuteState() {
+        mLayout.setMutable(false);
+        mLayout.setMuted(false);
+
+        mVolumeIcon.callOnClick();
+
+        assertThat(mLayout.isMuted()).isFalse();
+    }
+
+    @Test
+    public void updateLayout_mute_volumeIconIsCorrect() {
+        mLayout.setMuted(true);
+        mLayout.updateLayout();
+
+        assertThat(mVolumeIcon.getDrawable().getLevel()).isEqualTo(0);
+    }
+
+    @Test
+    public void updateLayout_unmuteAndExpanded_volumeIconIsCorrect() {
+        mLayout.setMuted(false);
+        mLayout.setExpanded(true);
+        mLayout.updateLayout();
+
+        int expectedLevel = calculateVolumeLevel(TEST_LEFT_VOLUME_LEVEL, TEST_RIGHT_VOLUME_LEVEL);
+        assertThat(mVolumeIcon.getDrawable().getLevel()).isEqualTo(expectedLevel);
+    }
+
+    @Test
+    public void updateLayout_unmuteAndNotExpanded_volumeIconIsCorrect() {
+        mLayout.setMuted(false);
+        mLayout.setExpanded(false);
+        mLayout.updateLayout();
+
+        int expectedLevel = calculateVolumeLevel(TEST_UNIFIED_VOLUME_LEVEL,
+                TEST_UNIFIED_VOLUME_LEVEL);
+        assertThat(mVolumeIcon.getDrawable().getLevel()).isEqualTo(expectedLevel);
+    }
+
+    @Test
+    public void setSliderEnabled_expandedAndLeftIsDisabled_volumeIconIsCorrect() {
+        mLayout.setExpanded(true);
+        mLayout.setSliderEnabled(SIDE_LEFT, false);
+
+        int expectedLevel = calculateVolumeLevel(0, TEST_RIGHT_VOLUME_LEVEL);
+        assertThat(mVolumeIcon.getDrawable().getLevel()).isEqualTo(expectedLevel);
+    }
+
+    @Test
+    public void setSliderValue_expandedAndLeftValueChanged_volumeIconIsCorrect() {
+        mLayout.setExpanded(true);
+        mLayout.setSliderValue(SIDE_LEFT, 4);
+
+        int expectedLevel = calculateVolumeLevel(4, TEST_RIGHT_VOLUME_LEVEL);
+        assertThat(mVolumeIcon.getDrawable().getLevel()).isEqualTo(expectedLevel);
+    }
+
+    private int calculateVolumeLevel(int left, int right) {
+        return left * 5 + right;
+    }
+
+    private void assertControlUiCorrect() {
+        final boolean expanded = mLayout.isExpanded();
+        final Map<Integer, AmbientVolumeSlider> sliders = mLayout.getSliders();
+        if (expanded) {
+            assertThat(sliders.get(SIDE_UNIFIED).getVisibility()).isEqualTo(GONE);
+            assertThat(sliders.get(SIDE_LEFT).getVisibility()).isEqualTo(VISIBLE);
+            assertThat(sliders.get(SIDE_RIGHT).getVisibility()).isEqualTo(VISIBLE);
+            assertThat(mExpandIcon.getRotation()).isEqualTo(ROTATION_EXPANDED);
+        } else {
+            assertThat(sliders.get(SIDE_UNIFIED).getVisibility()).isEqualTo(VISIBLE);
+            assertThat(sliders.get(SIDE_LEFT).getVisibility()).isEqualTo(GONE);
+            assertThat(sliders.get(SIDE_RIGHT).getVisibility()).isEqualTo(GONE);
+            assertThat(mExpandIcon.getRotation()).isEqualTo(ROTATION_COLLAPSED);
+        }
+    }
+
+    private void prepareDevices() {
+        mSideToDeviceMap.put(SIDE_LEFT, mock(BluetoothDevice.class));
+        mSideToDeviceMap.put(SIDE_RIGHT, mock(BluetoothDevice.class));
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSliderTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSliderTest.java
new file mode 100644
index 0000000..78dfda8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSliderTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/** Tests for {@link AmbientVolumeLayout}. */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class AmbientVolumeSliderTest extends SysuiTestCase {
+
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Spy
+    private Context mContext = ApplicationProvider.getApplicationContext();
+
+    private AmbientVolumeSlider mSlider;
+
+    @Before
+    public void setUp() {
+        mSlider = new AmbientVolumeSlider(mContext);
+    }
+
+    @Test
+    public void setTitle_titleCorrect() {
+        final String testTitle = "test";
+        mSlider.setTitle(testTitle);
+
+        assertThat(mSlider.getTitle()).isEqualTo(testTitle);
+    }
+
+    @Test
+    public void getVolumeLevel_valueMin_volumeLevelIsZero() {
+        prepareSlider(/* min= */ 0, /* max= */ 100, /* value= */ 0);
+
+        // The volume level is divided into 5 levels:
+        // Level 0 corresponds to the minimum volume value. The range between the minimum and
+        // maximum volume is divided into 4 equal intervals, represented by levels 1 to 4.
+        assertThat(mSlider.getVolumeLevel()).isEqualTo(0);
+    }
+
+    @Test
+    public void getVolumeLevel_valueMax_volumeLevelIsFour() {
+        prepareSlider(/* min= */ 0, /* max= */ 100, /* value= */ 100);
+
+        assertThat(mSlider.getVolumeLevel()).isEqualTo(4);
+    }
+
+    @Test
+    public void getVolumeLevel_volumeLevelIsCorrect() {
+        prepareSlider(/* min= */ 0, /* max= */ 100, /* value= */ 73);
+
+        assertThat(mSlider.getVolumeLevel()).isEqualTo(3);
+    }
+
+    private void prepareSlider(float min, float max, float value) {
+        mSlider.setMin(min);
+        mSlider.setMax(max);
+        mSlider.setValue(value);
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
index ad12c61..43d0d69c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
@@ -16,8 +16,11 @@
 
 package com.android.systemui.accessibility.hearingaid;
 
+import static android.bluetooth.BluetoothDevice.BOND_BONDED;
 import static android.bluetooth.BluetoothHapClient.PRESET_INDEX_UNAVAILABLE;
+import static android.bluetooth.BluetoothProfile.STATE_CONNECTED;
 
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
 import static com.android.systemui.accessibility.hearingaid.HearingDevicesDialogDelegate.LIVE_CAPTION_INTENT;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -31,6 +34,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.bluetooth.AudioInputControl;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHapPresetInfo;
 import android.bluetooth.BluetoothProfile;
@@ -61,6 +65,7 @@
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.bluetooth.VolumeControlProfile;
 import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogTransitionAnimator;
@@ -90,6 +95,7 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 public class HearingDevicesDialogDelegateTest extends SysuiTestCase {
+
     @Rule
     public MockitoRule mockito = MockitoJUnit.rule();
 
@@ -120,6 +126,8 @@
     @Mock
     private HapClientProfile mHapClientProfile;
     @Mock
+    private VolumeControlProfile mVolumeControlProfile;
+    @Mock
     private CachedBluetoothDeviceManager mCachedDeviceManager;
     @Mock
     private BluetoothEventManager mBluetoothEventManager;
@@ -151,21 +159,25 @@
         when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
         when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
         when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
+        when(mProfileManager.getVolumeControlProfile()).thenReturn(mVolumeControlProfile);
         when(mLocalBluetoothAdapter.isEnabled()).thenReturn(true);
         when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
         when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(List.of(mCachedDevice));
         when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
         when(mSysUiState.setFlag(anyLong(), anyBoolean())).thenReturn(mSysUiState);
-        when(mDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice.getBondState()).thenReturn(BOND_BONDED);
         when(mDevice.isConnected()).thenReturn(true);
         when(mCachedDevice.getDevice()).thenReturn(mDevice);
         when(mCachedDevice.getAddress()).thenReturn(DEVICE_ADDRESS);
         when(mCachedDevice.getName()).thenReturn(DEVICE_NAME);
-        when(mCachedDevice.getProfiles()).thenReturn(List.of(mHapClientProfile));
+        when(mCachedDevice.getProfiles()).thenReturn(
+                List.of(mHapClientProfile, mVolumeControlProfile));
         when(mCachedDevice.isActiveDevice(BluetoothProfile.HEARING_AID)).thenReturn(true);
         when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
         when(mCachedDevice.isConnectedHapClientDevice()).thenReturn(true);
         when(mCachedDevice.getDrawableWithDescription()).thenReturn(new Pair<>(mDrawable, ""));
+        when(mCachedDevice.getBondState()).thenReturn(BOND_BONDED);
+        when(mCachedDevice.getDeviceSide()).thenReturn(SIDE_LEFT);
         when(mHearingDeviceItem.getCachedBluetoothDevice()).thenReturn(mCachedDevice);
 
         mContext.setMockPackageManager(mPackageManager);
@@ -292,6 +304,46 @@
     }
 
     @Test
+    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICES_AMBIENT_VOLUME_CONTROL)
+    public void showDialog_deviceNotSupportVcp_ambientLayoutGone() {
+        when(mCachedDevice.getProfiles()).thenReturn(List.of());
+
+        setUpDeviceDialogWithoutPairNewDeviceButton();
+        mDialog.show();
+
+        ViewGroup ambientLayout = getAmbientLayout(mDialog);
+        assertThat(ambientLayout.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICES_AMBIENT_VOLUME_CONTROL)
+    public void showDialog_ambientControlNotAvailable_ambientLayoutGone() {
+        when(mVolumeControlProfile.getAudioInputControlServices(mDevice)).thenReturn(List.of());
+
+        setUpDeviceDialogWithoutPairNewDeviceButton();
+        mDialog.show();
+
+        ViewGroup ambientLayout = getAmbientLayout(mDialog);
+        assertThat(ambientLayout.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_HEARING_DEVICES_AMBIENT_VOLUME_CONTROL)
+    public void showDialog_supportVcpAndAmbientControlAvailable_ambientLayoutVisible() {
+        when(mCachedDevice.getProfiles()).thenReturn(List.of(mVolumeControlProfile));
+        AudioInputControl audioInputControl = prepareAudioInputControl();
+        when(mVolumeControlProfile.getAudioInputControlServices(mDevice)).thenReturn(
+                List.of(audioInputControl));
+        when(mVolumeControlProfile.getConnectionStatus(mDevice)).thenReturn(STATE_CONNECTED);
+
+        setUpDeviceDialogWithoutPairNewDeviceButton();
+        mDialog.show();
+
+        ViewGroup ambientLayout = getAmbientLayout(mDialog);
+        assertThat(ambientLayout.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
     public void onActiveDeviceChanged_presetExist_presetSelected() {
         setUpDeviceDialogWithoutPairNewDeviceButton();
         mDialog.show();
@@ -368,6 +420,10 @@
         return dialog.requireViewById(R.id.preset_layout);
     }
 
+    private ViewGroup getAmbientLayout(SystemUIDialog dialog) {
+        return dialog.requireViewById(R.id.ambient_layout);
+    }
+
 
     private int countChildWithoutSpace(ViewGroup viewGroup) {
         int spaceCount = 0;
@@ -388,6 +444,16 @@
         assertThat(toolsLayout.getVisibility()).isEqualTo(targetVisibility);
     }
 
+    private AudioInputControl prepareAudioInputControl() {
+        AudioInputControl audioInputControl = mock(AudioInputControl.class);
+        when(audioInputControl.getAudioInputType()).thenReturn(
+                AudioInputControl.AUDIO_INPUT_TYPE_AMBIENT);
+        when(audioInputControl.getGainMode()).thenReturn(AudioInputControl.GAIN_MODE_MANUAL);
+        when(audioInputControl.getAudioInputStatus()).thenReturn(
+                AudioInputControl.AUDIO_INPUT_STATUS_ACTIVE);
+        return audioInputControl;
+    }
+
     @After
     public void reset() {
         if (mDialogDelegate != null) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt
index fa5af51..77e3869 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.kt
@@ -127,6 +127,7 @@
     @Test
     @DisableFlags(
         Flags.FLAG_COMMUNAL_HUB,
+        Flags.FLAG_GLANCEABLE_HUB_V2,
         Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX,
         Flags.FLAG_SCENE_CONTAINER,
     )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
index 41cc6ee..cbb6f81 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.back.domain.interactor
 
+import android.platform.test.annotations.EnableFlags
 import android.platform.test.annotations.RequiresFlagsDisabled
 import android.platform.test.annotations.RequiresFlagsEnabled
 import android.platform.test.flag.junit.DeviceFlagsValueProvider
@@ -31,6 +32,7 @@
 import com.android.internal.statusbar.IStatusBarService
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.CommunalBackActionInteractor
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
@@ -93,6 +95,7 @@
     @Mock private lateinit var onBackInvokedDispatcher: WindowOnBackInvokedDispatcher
     @Mock private lateinit var iStatusBarService: IStatusBarService
     @Mock private lateinit var headsUpManager: HeadsUpManager
+    @Mock private lateinit var communalBackActionInteractor: CommunalBackActionInteractor
 
     private val keyguardRepository = FakeKeyguardRepository()
     private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor by lazy {
@@ -117,6 +120,7 @@
             windowRootViewVisibilityInteractor,
             shadeBackActionInteractor,
             qsController,
+            communalBackActionInteractor,
         )
     }
 
@@ -164,17 +168,6 @@
     }
 
     @Test
-    fun testOnBackRequested_closeUserSwitcherIfOpen() {
-        whenever(shadeBackActionInteractor.closeUserSwitcherIfOpen()).thenReturn(true)
-
-        val result = backActionInteractor.onBackRequested()
-
-        assertTrue(result)
-        verify(statusBarKeyguardViewManager, never()).onBackPressed()
-        verify(shadeBackActionInteractor, never()).animateCollapseQs(anyBoolean())
-    }
-
-    @Test
     fun testOnBackRequested_returnsFalse() {
         // make shouldBackBeHandled return false
         whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
@@ -306,6 +299,19 @@
         verify(shadeBackActionInteractor).onBackProgressed(0.4f)
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_GLANCEABLE_HUB_BACK_ACTION)
+    fun onBackAction_communalCanBeDismissed_communalBackActionInteractorCalled() {
+        backActionInteractor.start()
+        windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true)
+        powerInteractor.setAwakeForTest()
+        val callback = getBackInvokedCallback()
+        whenever(communalBackActionInteractor.canBeDismissed()).thenReturn(true)
+        callback.onBackInvoked()
+
+        verify(communalBackActionInteractor).onBackPressed()
+    }
+
     private fun getBackInvokedCallback(): OnBackInvokedCallback {
         testScope.runCurrent()
         val captor = argumentCaptor<OnBackInvokedCallback>()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
index 714461b..daebf13 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java
@@ -88,7 +88,7 @@
 
         listener.enable();
         verify(mDisplayManager).registerDisplayListener(any(), same(mHandler),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED));
     }
 
     @Test
@@ -112,7 +112,7 @@
 
         // The listener should register a display listener.
         verify(mDisplayManager).registerDisplayListener(mDisplayListenerCaptor.capture(),
-                same(mHandler), eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED));
+                same(mHandler), eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED));
 
         // mOnChangedCallback should be invoked for all calls to onDisplayChanged.
         mDisplayListenerCaptor.getValue().onDisplayChanged(123);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
index 08f139c..9c9d5ad 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequestTest.kt
@@ -51,7 +51,7 @@
                     title = title,
                     subtitle = subtitle,
                     description = description,
-                    contentView = contentView
+                    contentView = contentView,
                 ),
                 BiometricUserInfo(USER_ID),
                 BiometricOperationInfo(OPERATION_ID),
@@ -101,9 +101,7 @@
         val fpPros = fingerprintSensorPropertiesInternal().first()
         val request =
             BiometricPromptRequest.Biometric(
-                promptInfo(
-                    logoBitmap = logoBitmap,
-                ),
+                promptInfo(logoBitmap = logoBitmap),
                 BiometricUserInfo(USER_ID),
                 BiometricOperationInfo(OPERATION_ID),
                 BiometricModalities(fingerprintProperties = fpPros),
@@ -162,7 +160,7 @@
                     BiometricUserInfo(USER_ID),
                     BiometricOperationInfo(OPERATION_ID),
                     stealth,
-                )
+                ),
             )
 
         for (request in toCheck) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
index f4cffc5..2e8efdb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/brightness/data/repository/ScreenBrightnessDisplayManagerRepositoryTest.kt
@@ -20,7 +20,7 @@
 import android.hardware.display.BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE
 import android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
 import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS
 import android.view.Display
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -120,7 +120,7 @@
                         capture(listenerCaptor),
                         eq(null),
                         eq(0),
-                        eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
+                        eq(PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS),
                     )
 
                 val newBrightness = BrightnessInfo(0.6f, 0.3f, 0.9f)
@@ -159,7 +159,7 @@
                         capture(listenerCaptor),
                         eq(null),
                         eq(0),
-                        eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
+                        eq(PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS),
                     )
 
                 changeBrightnessInfoAndNotify(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalMetricsStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalMetricsStartableTest.kt
index 370adee..03bf79b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalMetricsStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalMetricsStartableTest.kt
@@ -19,6 +19,7 @@
 import android.app.StatsManager
 import android.app.StatsManager.StatsPullAtomCallback
 import android.content.pm.UserInfo
+import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.util.StatsEvent
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -32,6 +33,7 @@
 import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
 import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.kosmos.runTest
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.settings.fakeUserTracker
 import com.android.systemui.shared.system.SysUiStatsLog
@@ -75,10 +77,7 @@
         // Set up an existing user, which is required for widgets to show
         val userInfos = listOf(UserInfo(0, "main", UserInfo.FLAG_MAIN))
         userRepository.setUserInfos(userInfos)
-        userTracker.set(
-            userInfos = userInfos,
-            selectedUserIndex = 0,
-        )
+        userTracker.set(userInfos = userInfos, selectedUserIndex = 0)
 
         underTest =
             CommunalMetricsStartable(
@@ -90,14 +89,16 @@
             )
     }
 
+    @DisableFlags(Flags.FLAG_GLANCEABLE_HUB_V2)
     @Test
-    fun start_communalFlagDisabled_doNotSetPullAtomCallback() {
-        kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, false)
+    fun start_communalFlagDisabled_doNotSetPullAtomCallback() =
+        kosmos.runTest {
+            fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, false)
 
-        underTest.start()
+            underTest.start()
 
-        verify(statsManager, never()).setPullAtomCallback(anyInt(), anyOrNull(), any(), any())
-    }
+            verify(statsManager, never()).setPullAtomCallback(anyInt(), anyOrNull(), any(), any())
+        }
 
     @Test
     fun onPullAtom_atomTagDoesNotMatch_pullSkip() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
index b66727e..038ea9c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalSettingsRepositoryImplTest.kt
@@ -26,8 +26,8 @@
 import android.os.UserManager.USER_TYPE_PROFILE_MANAGED
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.FlagsParameterization
 import android.provider.Settings
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
@@ -35,10 +35,13 @@
 import com.android.systemui.broadcast.broadcastDispatcher
 import com.android.systemui.communal.data.model.DisabledReason
 import com.android.systemui.communal.data.repository.CommunalSettingsRepositoryImpl.Companion.GLANCEABLE_HUB_BACKGROUND_SETTING
+import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
 import com.android.systemui.communal.shared.model.CommunalBackgroundType
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
 import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.nullable
@@ -51,15 +54,21 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.eq
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class CommunalSettingsRepositoryImplTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class CommunalSettingsRepositoryImplTest(flags: FlagsParameterization?) : SysuiTestCase() {
     private val kosmos =
         testKosmos().apply { mainResources = mContext.orCreateTestableResources.resources }
     private val testScope = kosmos.testScope
     private lateinit var underTest: CommunalSettingsRepository
 
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Before
     fun setUp() {
         kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
@@ -164,17 +173,17 @@
             assertThat(enabledState).containsExactly(DisabledReason.DISABLED_REASON_INVALID_USER)
         }
 
-    @EnableFlags(FLAG_COMMUNAL_HUB)
+    @EnableFlags(FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2)
     @Test
     fun classicFlagIsDisabled() =
-        testScope.runTest {
-            kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, false)
+        kosmos.runTest {
+            setCommunalV2Enabled(false)
             val enabledState by collectLastValue(underTest.getEnabledState(PRIMARY_USER))
             assertThat(enabledState?.enabled).isFalse()
             assertThat(enabledState).containsExactly(DisabledReason.DISABLED_REASON_FLAG)
         }
 
-    @DisableFlags(FLAG_COMMUNAL_HUB)
+    @DisableFlags(FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2)
     @Test
     fun communalHubFlagIsDisabled() =
         testScope.runTest {
@@ -295,6 +304,34 @@
             }
         }
 
+    @Test
+    fun screensaverDisabledByUser() =
+        testScope.runTest {
+            val enabledState by collectLastValue(underTest.getScreensaverEnabledState(PRIMARY_USER))
+
+            kosmos.fakeSettings.putIntForUser(
+                Settings.Secure.SCREENSAVER_ENABLED,
+                0,
+                PRIMARY_USER.id,
+            )
+
+            assertThat(enabledState).isFalse()
+        }
+
+    @Test
+    fun screensaverEnabledByUser() =
+        testScope.runTest {
+            val enabledState by collectLastValue(underTest.getScreensaverEnabledState(PRIMARY_USER))
+
+            kosmos.fakeSettings.putIntForUser(
+                Settings.Secure.SCREENSAVER_ENABLED,
+                1,
+                PRIMARY_USER.id,
+            )
+
+            assertThat(enabledState).isTrue()
+        }
+
     private fun setKeyguardFeaturesDisabled(user: UserInfo, disabledFlags: Int) {
         whenever(kosmos.devicePolicyManager.getKeyguardDisabledFeatures(nullable(), eq(user.id)))
             .thenReturn(disabledFlags)
@@ -310,5 +347,11 @@
         val SECONDARY_USER = UserInfo(/* id= */ 1, /* name= */ "secondary user", /* flags= */ 0)
         val WORK_PROFILE =
             UserInfo(10, "work", /* iconPath= */ "", /* flags= */ 0, USER_TYPE_PROFILE_MANAGED)
+
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf(FLAG_GLANCEABLE_HUB_V2)
+        }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt
new file mode 100644
index 0000000..c365f1c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.domain.interactor
+
+import android.platform.test.annotations.EnableFlags
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.repository.communalSceneRepository
+import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.runCurrent
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+class CommunalBackActionInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+
+    private var Kosmos.underTest by Fixture { communalBackActionInteractor }
+
+    @Test
+    @EnableFlags(FLAG_COMMUNAL_HUB)
+    fun communalShowing_canBeDismissed() =
+        kosmos.runTest {
+            setCommunalAvailable(true)
+            assertThat(underTest.canBeDismissed()).isEqualTo(false)
+            communalInteractor.changeScene(CommunalScenes.Communal, "test")
+            runCurrent()
+            assertThat(underTest.canBeDismissed()).isEqualTo(true)
+        }
+
+    @Test
+    @EnableFlags(FLAG_COMMUNAL_HUB)
+    fun onBackPressed_invokesSceneChange() =
+        kosmos.runTest {
+            underTest.onBackPressed()
+            runCurrent()
+            assertThat(communalSceneRepository.currentScene.value).isEqualTo(CommunalScenes.Blank)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index b9e646f..7ae0577 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.Flags.FLAG_COMMUNAL_RESPONSIVE_GRID
 import com.android.systemui.Flags.FLAG_COMMUNAL_WIDGET_RESIZING
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.broadcastDispatcher
 import com.android.systemui.communal.data.model.CommunalSmartspaceTimer
@@ -232,7 +233,7 @@
     @Test
     fun isCommunalAvailable_communalDisabled_false() =
         testScope.runTest {
-            mSetFlagsRule.disableFlags(FLAG_COMMUNAL_HUB)
+            mSetFlagsRule.disableFlags(FLAG_COMMUNAL_HUB, FLAG_GLANCEABLE_HUB_V2)
 
             val isAvailable by collectLastValue(underTest.isCommunalAvailable)
             assertThat(isAvailable).isFalse()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
index 0bfcd24..8a9c42d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
@@ -130,19 +130,6 @@
         }
 
     @Test
-    fun tutorialState_startedAndCommunalSceneShowing_stateWillNotUpdate() =
-        testScope.runTest {
-            val tutorialSettingState by
-                collectLastValue(communalTutorialRepository.tutorialSettingState)
-
-            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
-
-            goToCommunal()
-
-            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED)
-        }
-
-    @Test
     fun tutorialState_completedAndCommunalSceneShowing_stateWillNotUpdate() =
         testScope.runTest {
             val tutorialSettingState by
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModelTest.kt
index a8a3873..9271980 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModelTest.kt
@@ -30,6 +30,7 @@
 import com.android.systemui.communal.widgets.GlanceableHubWidgetManager
 import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.backgroundCoroutineContext
 import com.android.systemui.kosmos.runCurrent
 import com.android.systemui.kosmos.runTest
@@ -57,8 +58,8 @@
 
     private val Kosmos.listenerDelegateFactory by
         Kosmos.Fixture {
-            AppWidgetHostListenerDelegate.Factory { listener ->
-                AppWidgetHostListenerDelegate(fakeExecutor, listener)
+            AppWidgetHostListenerDelegate.Factory { tag, listener ->
+                AppWidgetHostListenerDelegate(applicationCoroutineScope, tag, listener)
             }
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
index 8820685..012ae8f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelTest.kt
@@ -17,11 +17,14 @@
 package com.android.systemui.communal.ui.viewmodel
 
 import android.platform.test.annotations.EnableFlags
+import android.provider.Settings
 import android.service.dream.dreamManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.internal.logging.uiEventLoggerFake
 import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.shared.log.CommunalUiEvent
 import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.collectLastValue
@@ -29,12 +32,16 @@
 import com.android.systemui.kosmos.runTest
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.lifecycle.activateIn
+import com.android.systemui.plugins.activityStarter
 import com.android.systemui.statusbar.policy.batteryController
 import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.fakeUserRepository
+import com.android.systemui.util.settings.fakeSettings
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mockito.verify
 import org.mockito.kotlin.any
 import org.mockito.kotlin.whenever
@@ -45,6 +52,7 @@
 class CommunalToDreamButtonViewModelTest : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
+    private val uiEventLoggerFake = kosmos.uiEventLoggerFake
     private val underTest: CommunalToDreamButtonViewModel by lazy {
         kosmos.communalToDreamButtonViewModel
     }
@@ -56,10 +64,9 @@
     }
 
     @Test
-    fun shouldShowDreamButtonOnHub_trueWhenCanDream() =
+    fun shouldShowDreamButtonOnHub_trueWhenPluggedIn() =
         with(kosmos) {
             runTest {
-                whenever(dreamManager.canStartDreaming(any())).thenReturn(true)
                 whenever(batteryController.isPluggedIn()).thenReturn(true)
 
                 val shouldShowButton by collectLastValue(underTest.shouldShowDreamButtonOnHub)
@@ -68,22 +75,9 @@
         }
 
     @Test
-    fun shouldShowDreamButtonOnHub_falseWhenCannotDream() =
-        with(kosmos) {
-            runTest {
-                whenever(dreamManager.canStartDreaming(any())).thenReturn(false)
-                whenever(batteryController.isPluggedIn()).thenReturn(true)
-
-                val shouldShowButton by collectLastValue(underTest.shouldShowDreamButtonOnHub)
-                assertThat(shouldShowButton).isFalse()
-            }
-        }
-
-    @Test
     fun shouldShowDreamButtonOnHub_falseWhenNotPluggedIn() =
         with(kosmos) {
             runTest {
-                whenever(dreamManager.canStartDreaming(any())).thenReturn(true)
                 whenever(batteryController.isPluggedIn()).thenReturn(false)
 
                 val shouldShowButton by collectLastValue(underTest.shouldShowDreamButtonOnHub)
@@ -92,13 +86,52 @@
         }
 
     @Test
-    fun onShowDreamButtonTap_startsDream() =
+    fun onShowDreamButtonTap_dreamsEnabled_startsDream() =
+        with(kosmos) {
+            runTest {
+                val currentUser = fakeUserRepository.asMainUser()
+                kosmos.fakeSettings.putIntForUser(
+                    Settings.Secure.SCREENSAVER_ENABLED,
+                    1,
+                    currentUser.id,
+                )
+                runCurrent()
+
+                underTest.onShowDreamButtonTap()
+                runCurrent()
+
+                verify(dreamManager).startDream()
+            }
+        }
+
+    @Test
+    fun onShowDreamButtonTap_dreamsDisabled_startsActivity() =
+        with(kosmos) {
+            runTest {
+                val currentUser = fakeUserRepository.asMainUser()
+                kosmos.fakeSettings.putIntForUser(
+                    Settings.Secure.SCREENSAVER_ENABLED,
+                    0,
+                    currentUser.id,
+                )
+                runCurrent()
+
+                underTest.onShowDreamButtonTap()
+                runCurrent()
+
+                verify(activityStarter).postStartActivityDismissingKeyguard(any(), anyInt())
+            }
+        }
+
+    @Test
+    fun onShowDreamButtonTap_eventLogged() =
         with(kosmos) {
             runTest {
                 underTest.onShowDreamButtonTap()
                 runCurrent()
 
-                verify(dreamManager).startDream()
+                assertThat(uiEventLoggerFake[0].eventId)
+                    .isEqualTo(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP.id)
             }
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalWidgetHostTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalWidgetHostTest.kt
index 017c778..214cd1a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalWidgetHostTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalWidgetHostTest.kt
@@ -27,10 +27,11 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.communal.shared.model.fakeGlanceableHubMultiUserHelper
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.coroutines.collectValues
 import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.collectValues
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
 import com.android.systemui.log.logcatLogBuffer
 import com.android.systemui.testKosmos
 import com.android.systemui.user.data.model.SelectedUserModel
@@ -43,10 +44,6 @@
 import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -58,11 +55,9 @@
 import org.mockito.MockitoAnnotations
 
 @SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(AndroidJUnit4::class)
 class CommunalWidgetHostTest : SysuiTestCase() {
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
+    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
 
     @Mock private lateinit var appWidgetManager: AppWidgetManager
     @Mock private lateinit var appWidgetHost: CommunalAppWidgetHost
@@ -103,12 +98,11 @@
 
     @Test
     fun allocateIdAndBindWidget_withCurrentUser() =
-        testScope.runTest {
+        kosmos.runTest {
             val provider = ComponentName("pkg_name", "cls_name")
             val widgetId = 1
             val userId by collectLastValue(selectedUserInteractor.selectedUser)
             selectUser()
-            runCurrent()
 
             val user = UserHandle(checkNotNull(userId))
             whenever(appWidgetHost.allocateAppWidgetId()).thenReturn(widgetId)
@@ -129,7 +123,7 @@
 
     @Test
     fun allocateIdAndBindWidget_onSuccess() =
-        testScope.runTest {
+        kosmos.runTest {
             val provider = ComponentName("pkg_name", "cls_name")
             val widgetId = 1
             val user = UserHandle(0)
@@ -152,7 +146,7 @@
 
     @Test
     fun allocateIdAndBindWidget_onFailure() =
-        testScope.runTest {
+        kosmos.runTest {
             val provider = ComponentName("pkg_name", "cls_name")
             val widgetId = 1
             val user = UserHandle(0)
@@ -179,12 +173,11 @@
 
     @Test
     fun listener_exactlyOneListenerRegisteredForEachWidgetWhenHostStartListening() =
-        testScope.runTest {
+        kosmos.runTest {
             // 3 widgets registered with the host
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2, 3))
 
             underTest.startObservingHost()
-            runCurrent()
 
             // Make sure no listener is set before host starts listening
             verify(appWidgetHost, never()).setListener(any(), any())
@@ -195,7 +188,6 @@
                     verify(appWidgetHost).addObserver(capture())
                 }
             observer.onHostStartListening()
-            runCurrent()
 
             // Verify a listener is set for each widget
             verify(appWidgetHost, times(3)).setListener(any(), any())
@@ -206,12 +198,11 @@
 
     @Test
     fun listener_listenersRemovedWhenHostStopListening() =
-        testScope.runTest {
+        kosmos.runTest {
             // 3 widgets registered with the host
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2, 3))
 
             underTest.startObservingHost()
-            runCurrent()
 
             // Host starts listening
             val observer =
@@ -219,7 +210,6 @@
                     verify(appWidgetHost).addObserver(capture())
                 }
             observer.onHostStartListening()
-            runCurrent()
 
             // Verify none of the listener is removed before host stop listening
             verify(appWidgetHost, never()).removeListener(any())
@@ -235,7 +225,7 @@
 
     @Test
     fun listener_addNewListenerWhenNewIdAllocated() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf())
             val observer = start()
 
@@ -251,7 +241,7 @@
 
     @Test
     fun listener_removeListenerWhenWidgetDeleted() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1))
             val observer = start()
 
@@ -267,7 +257,7 @@
 
     @Test
     fun providerInfo_populatesWhenStartListening() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2))
             whenever(appWidgetManager.getAppWidgetInfo(1)).thenReturn(providerInfo1)
             whenever(appWidgetManager.getAppWidgetInfo(2)).thenReturn(providerInfo2)
@@ -279,7 +269,6 @@
             assertThat(providerInfoValues[0]).isEmpty()
 
             start()
-            runCurrent()
 
             // Assert that the provider info map is populated after host started listening, and that
             // all providers are emitted at once
@@ -290,13 +279,12 @@
 
     @Test
     fun providerInfo_clearsWhenStopListening() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2))
             whenever(appWidgetManager.getAppWidgetInfo(1)).thenReturn(providerInfo1)
             whenever(appWidgetManager.getAppWidgetInfo(2)).thenReturn(providerInfo2)
 
             val observer = start()
-            runCurrent()
 
             // Assert that the provider info map is populated
             val providerInfo by collectLastValue(underTest.appWidgetProviders)
@@ -312,7 +300,7 @@
 
     @Test
     fun providerInfo_onUpdate() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2))
             whenever(appWidgetManager.getAppWidgetInfo(1)).thenReturn(providerInfo1)
             whenever(appWidgetManager.getAppWidgetInfo(2)).thenReturn(providerInfo2)
@@ -320,7 +308,6 @@
             val providerInfo by collectLastValue(underTest.appWidgetProviders)
 
             start()
-            runCurrent()
 
             // Assert that the provider info map is populated
             assertThat(providerInfo)
@@ -332,7 +319,6 @@
                     verify(appWidgetHost).setListener(eq(1), capture())
                 }
             listener.onUpdateProviderInfo(providerInfo3)
-            runCurrent()
 
             // Assert that the update is reflected in the flow
             assertThat(providerInfo)
@@ -341,7 +327,7 @@
 
     @Test
     fun providerInfo_updateWhenANewWidgetIsBound() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2))
             whenever(appWidgetManager.getAppWidgetInfo(1)).thenReturn(providerInfo1)
             whenever(appWidgetManager.getAppWidgetInfo(2)).thenReturn(providerInfo2)
@@ -349,7 +335,6 @@
             val providerInfo by collectLastValue(underTest.appWidgetProviders)
 
             start()
-            runCurrent()
 
             // Assert that the provider info map is populated
             assertThat(providerInfo)
@@ -360,7 +345,6 @@
             whenever(appWidgetManager.getAppWidgetInfo(3)).thenReturn(providerInfo3)
             val newWidgetComponentName = ComponentName.unflattenFromString("pkg_new/cls_new")!!
             underTest.allocateIdAndBindWidget(newWidgetComponentName)
-            runCurrent()
 
             // Assert that the new provider is reflected in the flow
             assertThat(providerInfo)
@@ -371,7 +355,7 @@
 
     @Test
     fun providerInfo_updateWhenWidgetRemoved() =
-        testScope.runTest {
+        kosmos.runTest {
             whenever(appWidgetHost.appWidgetIds).thenReturn(intArrayOf(1, 2))
             whenever(appWidgetManager.getAppWidgetInfo(1)).thenReturn(providerInfo1)
             whenever(appWidgetManager.getAppWidgetInfo(2)).thenReturn(providerInfo2)
@@ -379,7 +363,6 @@
             val providerInfo by collectLastValue(underTest.appWidgetProviders)
 
             val observer = start()
-            runCurrent()
 
             // Assert that the provider info map is populated
             assertThat(providerInfo)
@@ -387,7 +370,6 @@
 
             // Remove widget 1
             observer.onDeleteAppWidgetId(1)
-            runCurrent()
 
             // Assert that provider info for widget 1 is removed
             assertThat(providerInfo).containsExactlyEntriesIn(mapOf(Pair(2, providerInfo2)))
@@ -401,9 +383,8 @@
             )
     }
 
-    private fun TestScope.start(): CommunalAppWidgetHost.Observer {
+    private fun start(): CommunalAppWidgetHost.Observer {
         underTest.startObservingHost()
-        runCurrent()
 
         val observer =
             withArgCaptor<CommunalAppWidgetHost.Observer> {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/controls/ui/ControlActionCoordinatorImplTest.kt
similarity index 80%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/controls/ui/ControlActionCoordinatorImplTest.kt
index 9285146..c8661cf5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/controls/ui/ControlActionCoordinatorImplTest.kt
@@ -16,9 +16,9 @@
 
 package com.android.systemui.controls.ui
 
+import android.view.HapticFeedbackConstants
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import android.view.HapticFeedbackConstants
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastSender
 import com.android.systemui.controls.ControlsMetricsLogger
@@ -29,6 +29,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.concurrency.DelayableExecutor
 import com.android.wm.shell.taskview.TaskViewFactory
+import java.util.Optional
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -45,31 +46,20 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
-import java.util.Optional
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class ControlActionCoordinatorImplTest : SysuiTestCase() {
-    @Mock
-    private lateinit var vibratorHelper: VibratorHelper
-    @Mock
-    private lateinit var keyguardStateController: KeyguardStateController
-    @Mock
-    private lateinit var bgExecutor: DelayableExecutor
-    @Mock
-    private lateinit var uiExecutor: DelayableExecutor
-    @Mock
-    private lateinit var activityStarter: ActivityStarter
-    @Mock
-    private lateinit var broadcastSender: BroadcastSender
-    @Mock
-    private lateinit var taskViewFactory: Optional<TaskViewFactory>
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private lateinit var cvh: ControlViewHolder
-    @Mock
-    private lateinit var metricsLogger: ControlsMetricsLogger
-    @Mock
-    private lateinit var controlsSettingsDialogManager: ControlsSettingsDialogManager
+    @Mock private lateinit var vibratorHelper: VibratorHelper
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var bgExecutor: DelayableExecutor
+    @Mock private lateinit var uiExecutor: DelayableExecutor
+    @Mock private lateinit var activityStarter: ActivityStarter
+    @Mock private lateinit var broadcastSender: BroadcastSender
+    @Mock private lateinit var taskViewFactory: Optional<TaskViewFactory>
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS) private lateinit var cvh: ControlViewHolder
+    @Mock private lateinit var metricsLogger: ControlsMetricsLogger
+    @Mock private lateinit var controlsSettingsDialogManager: ControlsSettingsDialogManager
 
     companion object {
         fun <T> any(): T = Mockito.any<T>()
@@ -89,18 +79,21 @@
         controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(true)
         controlsSettingsRepository.setCanShowControlsInLockscreen(true)
 
-        coordinator = spy(ControlActionCoordinatorImpl(
-                mContext,
-                bgExecutor,
-                uiExecutor,
-                activityStarter,
-                broadcastSender,
-                keyguardStateController,
-                taskViewFactory,
-                metricsLogger,
-                vibratorHelper,
-                controlsSettingsRepository,
-        ))
+        coordinator =
+            spy(
+                ControlActionCoordinatorImpl(
+                    mContext,
+                    bgExecutor,
+                    uiExecutor,
+                    activityStarter,
+                    broadcastSender,
+                    keyguardStateController,
+                    taskViewFactory,
+                    metricsLogger,
+                    vibratorHelper,
+                    controlsSettingsRepository,
+                )
+            )
         coordinator.activityContext = mContext
 
         `when`(cvh.cws.ci.controlId).thenReturn(ID)
@@ -198,19 +191,15 @@
     fun drag_isEdge_performsSegmentTickHaptics() {
         coordinator.drag(cvh, true)
 
-        verify(vibratorHelper).performHapticFeedback(
-            any(),
-            eq(HapticFeedbackConstants.SEGMENT_TICK)
-        )
+        verify(vibratorHelper)
+            .performHapticFeedback(any(), eq(HapticFeedbackConstants.SEGMENT_TICK))
     }
 
     @Test
     fun drag_isNotEdge_performsFrequentTickHaptics() {
         coordinator.drag(cvh, false)
 
-        verify(vibratorHelper).performHapticFeedback(
-            any(),
-            eq(HapticFeedbackConstants.SEGMENT_FREQUENT_TICK)
-        )
+        verify(vibratorHelper)
+            .performHapticFeedback(any(), eq(HapticFeedbackConstants.SEGMENT_FREQUENT_TICK))
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index e6e5665..c585d5c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -541,7 +541,7 @@
                 connectedDisplayListener.capture(),
                 eq(testHandler),
                 eq(0),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED),
             )
         return flowValue
     }
@@ -558,9 +558,9 @@
                 displayListener.capture(),
                 eq(testHandler),
                 eq(
-                    DisplayManager.EVENT_FLAG_DISPLAY_ADDED or
-                        DisplayManager.EVENT_FLAG_DISPLAY_CHANGED or
-                        DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
+                    DisplayManager.EVENT_TYPE_DISPLAY_ADDED or
+                        DisplayManager.EVENT_TYPE_DISPLAY_CHANGED or
+                        DisplayManager.EVENT_TYPE_DISPLAY_REMOVED
                 ),
             )
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index b07097d..5921e94 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -92,10 +92,10 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.Mockito
 import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.isNull
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
 import org.mockito.kotlin.argumentCaptor
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.firstValue
@@ -768,7 +768,7 @@
             runCurrent()
             verify(mDreamOverlayCallback).onRedirectWake(true)
             client.onWakeRequested()
-            verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), any(), isNull())
+            verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), any(), anyOrNull())
             verify(mUiEventLogger).log(CommunalUiEvent.DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START)
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsComponentInteractorTest.kt
similarity index 100%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/system/domain/interactor/HomeControlsComponentInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/homecontrols/HomeControlsComponentInteractorTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
index 9cfd328..f2a6c11 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/data/repository/ContextualEducationRepositoryTest.kt
@@ -36,6 +36,7 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
@@ -43,6 +44,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@Ignore("b/384284415")
 class ContextualEducationRepositoryTest : SysuiTestCase() {
 
     private lateinit var underTest: UserContextualEducationRepository
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
index 8bb6962..4630674 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/data/repository/TutorialSchedulerRepositoryTest.kt
@@ -22,13 +22,12 @@
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
 import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
-import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.backgroundScope
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
 import java.time.Instant
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.runTest
-import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -38,7 +37,7 @@
 class TutorialSchedulerRepositoryTest : SysuiTestCase() {
 
     private lateinit var underTest: TutorialSchedulerRepository
-    private val kosmos = Kosmos()
+    private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
 
     @Before
@@ -46,45 +45,57 @@
         underTest =
             TutorialSchedulerRepository(
                 context,
-                testScope.backgroundScope,
+                kosmos.backgroundScope,
                 "TutorialSchedulerRepositoryTest",
             )
     }
 
-    @After
-    fun clear() {
-        testScope.launch { underTest.clear() }
+    @Test
+    fun initialState() = runTestAndClear {
+        assertThat(underTest.wasEverConnected(KEYBOARD)).isFalse()
+        assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
+        assertThat(underTest.isNotified(KEYBOARD)).isFalse()
+        assertThat(underTest.isNotified(TOUCHPAD)).isFalse()
+        assertThat(underTest.isScheduledTutorialLaunched(KEYBOARD)).isFalse()
+        assertThat(underTest.isScheduledTutorialLaunched(TOUCHPAD)).isFalse()
     }
 
     @Test
-    fun initialState() =
-        testScope.runTest {
-            assertThat(underTest.wasEverConnected(KEYBOARD)).isFalse()
-            assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
-            assertThat(underTest.isLaunched(KEYBOARD)).isFalse()
-            assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
-        }
+    fun connectKeyboard() = runTestAndClear {
+        val now = Instant.now()
+        underTest.setFirstConnectionTime(KEYBOARD, now)
+
+        assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue()
+        assertThat(underTest.getFirstConnectionTime(KEYBOARD)!!.epochSecond)
+            .isEqualTo(now.epochSecond)
+        assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
+    }
 
     @Test
-    fun connectKeyboard() =
-        testScope.runTest {
-            val now = Instant.now()
-            underTest.updateFirstConnectionTime(KEYBOARD, now)
+    fun launchKeyboard() = runTestAndClear {
+        val now = Instant.now()
+        underTest.setScheduledTutorialLaunchTime(KEYBOARD, now)
 
-            assertThat(underTest.wasEverConnected(KEYBOARD)).isTrue()
-            assertThat(underTest.firstConnectionTime(KEYBOARD)!!.epochSecond)
-                .isEqualTo(now.epochSecond)
-            assertThat(underTest.wasEverConnected(TOUCHPAD)).isFalse()
-        }
+        assertThat(underTest.isScheduledTutorialLaunched(KEYBOARD)).isTrue()
+        assertThat(underTest.getScheduledTutorialLaunchTime(KEYBOARD)!!.epochSecond)
+            .isEqualTo(now.epochSecond)
+        assertThat(underTest.isScheduledTutorialLaunched(TOUCHPAD)).isFalse()
+    }
 
     @Test
-    fun launchKeyboard() =
-        testScope.runTest {
-            val now = Instant.now()
-            underTest.updateLaunchTime(KEYBOARD, now)
+    fun notifyKeyboard() = runTestAndClear {
+        underTest.setNotified(KEYBOARD)
 
-            assertThat(underTest.isLaunched(KEYBOARD)).isTrue()
-            assertThat(underTest.launchTime(KEYBOARD)!!.epochSecond).isEqualTo(now.epochSecond)
-            assertThat(underTest.isLaunched(TOUCHPAD)).isFalse()
+        assertThat(underTest.isNotified(KEYBOARD)).isTrue()
+        assertThat(underTest.isNotified(TOUCHPAD)).isFalse()
+    }
+
+    private fun runTestAndClear(block: suspend () -> Unit) =
+        testScope.runTest {
+            try {
+                block()
+            } finally {
+                underTest.clear()
+            }
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
index bcac086..886aa51 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.inputdevice.tutorial.inputDeviceTutorialLogger
 import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
 import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.kosmos.backgroundScope
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
 import com.android.systemui.settings.userTracker
@@ -34,14 +35,9 @@
 import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
 import com.google.common.truth.Truth.assertThat
 import kotlin.time.Duration.Companion.hours
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
-import org.junit.After
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -65,7 +61,6 @@
     private val testScope = kosmos.testScope
     private val keyboardRepository = FakeKeyboardRepository()
     private val touchpadRepository = FakeTouchpadRepository()
-    private lateinit var dataStoreScope: CoroutineScope
     private lateinit var repository: TutorialSchedulerRepository
     @Mock private lateinit var notificationManager: NotificationManager
     @Captor private lateinit var notificationCaptor: ArgumentCaptor<Notification>
@@ -73,11 +68,10 @@
 
     @Before
     fun setup() {
-        dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
         repository =
             TutorialSchedulerRepository(
                 context,
-                dataStoreScope,
+                kosmos.backgroundScope,
                 dataStoreName = "TutorialNotificationCoordinatorTest",
             )
         val interactor =
@@ -87,6 +81,7 @@
                 repository,
                 kosmos.inputDeviceTutorialLogger,
                 kosmos.commandRegistry,
+                testScope.backgroundScope,
             )
         underTest =
             TutorialNotificationCoordinator(
@@ -100,52 +95,51 @@
         underTest.start()
     }
 
-    @After
-    fun clear() {
-        runBlocking { repository.clear() }
-        dataStoreScope.cancel()
+    @Test
+    fun showKeyboardNotification() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
+        verifyNotification(
+            R.string.launch_keyboard_tutorial_notification_title,
+            R.string.launch_keyboard_tutorial_notification_content,
+        )
     }
 
     @Test
-    fun showKeyboardNotification() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            advanceTimeBy(LAUNCH_DELAY)
-            verifyNotification(
-                R.string.launch_keyboard_tutorial_notification_title,
-                R.string.launch_keyboard_tutorial_notification_content,
-            )
-        }
+    fun showTouchpadNotification() = runTestAndClear {
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
+        verifyNotification(
+            R.string.launch_touchpad_tutorial_notification_title,
+            R.string.launch_touchpad_tutorial_notification_content,
+        )
+    }
 
     @Test
-    fun showTouchpadNotification() =
-        testScope.runTest {
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            advanceTimeBy(LAUNCH_DELAY)
-            verifyNotification(
-                R.string.launch_touchpad_tutorial_notification_title,
-                R.string.launch_touchpad_tutorial_notification_content,
-            )
-        }
+    fun showKeyboardTouchpadNotification() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
+        verifyNotification(
+            R.string.launch_keyboard_touchpad_tutorial_notification_title,
+            R.string.launch_keyboard_touchpad_tutorial_notification_content,
+        )
+    }
 
     @Test
-    fun showKeyboardTouchpadNotification() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            advanceTimeBy(LAUNCH_DELAY)
-            verifyNotification(
-                R.string.launch_keyboard_touchpad_tutorial_notification_title,
-                R.string.launch_keyboard_touchpad_tutorial_notification_content,
-            )
-        }
+    fun doNotShowNotification() = runTestAndClear {
+        testScope.advanceTimeBy(LAUNCH_DELAY)
+        verify(notificationManager, never())
+            .notifyAsUser(eq(TAG), eq(NOTIFICATION_ID), any(), any())
+    }
 
-    @Test
-    fun doNotShowNotification() =
+    private fun runTestAndClear(block: suspend () -> Unit) =
         testScope.runTest {
-            advanceTimeBy(LAUNCH_DELAY)
-            verify(notificationManager, never())
-                .notifyAsUser(eq(TAG), eq(NOTIFICATION_ID), any(), any())
+            try {
+                block()
+            } finally {
+                repository.clear()
+            }
         }
 
     private fun verifyNotification(@StringRes titleResId: Int, @StringRes contentResId: Int) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
index 2efa2f3..722451e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
@@ -30,16 +30,11 @@
 import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
 import com.google.common.truth.Truth.assertThat
 import kotlin.time.Duration.Companion.hours
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runTest
-import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -52,18 +47,16 @@
     private lateinit var underTest: TutorialSchedulerInteractor
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
-    private lateinit var dataStoreScope: CoroutineScope
     private val keyboardRepository = FakeKeyboardRepository()
     private val touchpadRepository = FakeTouchpadRepository()
     private lateinit var schedulerRepository: TutorialSchedulerRepository
 
     @Before
     fun setup() {
-        dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
         schedulerRepository =
             TutorialSchedulerRepository(
                 context,
-                dataStoreScope,
+                testScope.backgroundScope,
                 dataStoreName = "TutorialSchedulerInteractorTest",
             )
         underTest =
@@ -73,98 +66,95 @@
                 schedulerRepository,
                 kosmos.inputDeviceTutorialLogger,
                 kosmos.commandRegistry,
+                testScope.backgroundScope,
             )
     }
 
-    @After
-    fun clear() {
-        runBlocking { schedulerRepository.clear() }
-        dataStoreScope.cancel()
+    @Test
+    fun connectKeyboard_delayElapse_notifyForKeyboard() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
+        notifyAndAssert(TutorialType.KEYBOARD)
     }
 
     @Test
-    fun connectKeyboard_delayElapse_launchForKeyboard() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            advanceTimeBy(LAUNCH_DELAY)
+    fun connectBothDevices_delayElapse_notifyForBoth() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
 
-            launchAndAssert(TutorialType.KEYBOARD)
-        }
+        notifyAndAssert(TutorialType.BOTH)
+    }
 
     @Test
-    fun connectBothDevices_delayElapse_launchForBoth() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            advanceTimeBy(LAUNCH_DELAY)
+    fun connectBothDevice_delayNotElapse_notifyNothing() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        testScope.advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
 
-            launchAndAssert(TutorialType.BOTH)
-        }
+        notifyAndAssert(TutorialType.NONE)
+    }
 
     @Test
-    fun connectBothDevice_delayNotElapse_launchNothing() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
+    fun nothingConnect_delayElapse_notifyNothing() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(false)
+        touchpadRepository.setIsAnyTouchpadConnected(false)
+        testScope.advanceTimeBy(LAUNCH_DELAY)
 
-            launchAndAssert(TutorialType.NONE)
-        }
+        notifyAndAssert(TutorialType.NONE)
+    }
 
     @Test
-    fun nothingConnect_delayElapse_launchNothing() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(false)
-            touchpadRepository.setIsAnyTouchpadConnected(false)
-            advanceTimeBy(LAUNCH_DELAY)
+    fun connectKeyboard_thenTouchpad_delayElapse_notifyForBoth() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        testScope.advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        testScope.advanceTimeBy(REMAINING_TIME)
 
-            launchAndAssert(TutorialType.NONE)
-        }
+        notifyAndAssert(TutorialType.BOTH)
+    }
 
     @Test
-    fun connectKeyboard_thenTouchpad_delayElapse_launchForBoth() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            advanceTimeBy(REMAINING_TIME)
+    fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_notifyNothing() = runTestAndClear {
+        keyboardRepository.setIsAnyKeyboardConnected(true)
+        testScope.advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
+        touchpadRepository.setIsAnyTouchpadConnected(true)
+        keyboardRepository.setIsAnyKeyboardConnected(false)
+        testScope.advanceTimeBy(REMAINING_TIME)
 
-            launchAndAssert(TutorialType.BOTH)
+        notifyAndAssert(TutorialType.NONE)
+    }
+
+    private fun runTestAndClear(block: suspend () -> Unit) =
+        testScope.runTest {
+            try {
+                block()
+            } finally {
+                schedulerRepository.clear()
+            }
         }
 
-    @Test
-    fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_launchNothing() =
-        testScope.runTest {
-            keyboardRepository.setIsAnyKeyboardConnected(true)
-            advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
-            touchpadRepository.setIsAnyTouchpadConnected(true)
-            keyboardRepository.setIsAnyKeyboardConnected(false)
-            advanceTimeBy(REMAINING_TIME)
-            launchAndAssert(TutorialType.NONE)
-        }
-
-    private suspend fun launchAndAssert(expectedTutorial: TutorialType) =
+    private fun notifyAndAssert(expectedTutorial: TutorialType) =
         testScope.backgroundScope.launch {
             val actualTutorial = underTest.tutorials.first()
             assertThat(actualTutorial).isEqualTo(expectedTutorial)
 
-            // TODO: need to update after we move launch into the tutorial
             when (expectedTutorial) {
                 TutorialType.KEYBOARD -> {
-                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
-                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+                    assertThat(schedulerRepository.isNotified(DeviceType.KEYBOARD)).isTrue()
+                    assertThat(schedulerRepository.isNotified(DeviceType.TOUCHPAD)).isFalse()
                 }
                 TutorialType.TOUCHPAD -> {
-                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
-                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+                    assertThat(schedulerRepository.isNotified(DeviceType.KEYBOARD)).isFalse()
+                    assertThat(schedulerRepository.isNotified(DeviceType.TOUCHPAD)).isTrue()
                 }
                 TutorialType.BOTH -> {
-                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
-                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+                    assertThat(schedulerRepository.isNotified(DeviceType.KEYBOARD)).isTrue()
+                    assertThat(schedulerRepository.isNotified(DeviceType.TOUCHPAD)).isTrue()
                 }
                 TutorialType.NONE -> {
-                    assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
-                    assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+                    assertThat(schedulerRepository.isNotified(DeviceType.KEYBOARD)).isFalse()
+                    assertThat(schedulerRepository.isNotified(DeviceType.TOUCHPAD)).isFalse()
                 }
             }
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
index ee3e241..56e8185 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfigTest.kt
@@ -81,7 +81,7 @@
         // Then
         verify(cameraGestureHelper)
             .launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
-        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(true), result)
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
index 50ac2619..fde9b8c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfigTest.kt
@@ -197,7 +197,7 @@
 
             val dndMode = currentModes!!.single()
             assertThat(dndMode.isActive).isFalse()
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
         }
 
     @Test
@@ -222,7 +222,7 @@
                 )
 
             // then
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
             assertEquals(ZEN_MODE_OFF, spyZenMode.value)
             assertNull(spyConditionId.value)
         }
@@ -244,7 +244,7 @@
             val dndMode = currentModes!!.single()
             assertThat(dndMode.isActive).isTrue()
             assertThat(zenModeRepository.getModeActiveDuration(dndMode.id)).isNull()
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
         }
 
     @Test
@@ -268,7 +268,7 @@
                 )
 
             // then
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
             assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
             assertNull(spyConditionId.value)
         }
@@ -285,7 +285,7 @@
             val result = underTest.onTriggered(null)
             runCurrent()
 
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
             val dndMode = currentModes!!.single()
             assertThat(dndMode.isActive).isTrue()
             assertThat(zenModeRepository.getModeActiveDuration(dndMode.id))
@@ -313,7 +313,7 @@
                 )
 
             // then
-            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
             assertEquals(ZEN_MODE_IMPORTANT_INTERRUPTIONS, spyZenMode.value)
             assertEquals(conditionUri, spyConditionId.value)
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigTest.kt
index 789b10b..ac06a3b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigTest.kt
@@ -24,21 +24,19 @@
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.communal.data.repository.communalSceneRepository
-import com.android.systemui.communal.domain.interactor.communalInteractor
-import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalV2Available
 import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
 import com.android.systemui.communal.shared.model.CommunalScenes
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.andSceneContainer
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.flags.parameterizeSceneContainerFlag
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runCurrent
+import com.android.systemui.kosmos.runTest
 import com.android.systemui.scene.data.repository.sceneContainerRepository
-import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -47,14 +45,11 @@
 import platform.test.runner.parameterized.Parameters
 
 @SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
-@EnableFlags(Flags.FLAG_GLANCEABLE_HUB_SHORTCUT_BUTTON, Flags.FLAG_GLANCEABLE_HUB_V2)
+@EnableFlags(Flags.FLAG_GLANCEABLE_HUB_V2)
 @RunWith(ParameterizedAndroidJunit4::class)
 class GlanceableHubQuickAffordanceConfigTest(flags: FlagsParameterization?) : SysuiTestCase() {
     private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-
-    private lateinit var underTest: GlanceableHubQuickAffordanceConfig
+    private val Kosmos.underTest by Kosmos.Fixture { glanceableHubQuickAffordanceConfig }
 
     init {
         mSetFlagsRule.setFlagsParameterization(flags!!)
@@ -64,20 +59,16 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        underTest =
-            GlanceableHubQuickAffordanceConfig(
-                context = context,
-                communalInteractor = kosmos.communalInteractor,
-                communalSceneRepository = kosmos.communalSceneRepository,
-                communalSettingsInteractor = kosmos.communalSettingsInteractor,
-                sceneInteractor = kosmos.sceneInteractor,
-            )
+        // Access the class immediately so that flows are instantiated.
+        // GlanceableHubQuickAffordanceConfig accesses StateFlow.value directly so we need the flows
+        // to start flowing before runCurrent is called in the tests.
+        kosmos.underTest
     }
 
     @Test
     fun lockscreenState_whenGlanceableHubEnabled_returnsVisible() =
-        testScope.runTest {
-            kosmos.setCommunalV2Enabled(true)
+        kosmos.runTest {
+            kosmos.setCommunalV2Available(true)
             runCurrent()
 
             val lockScreenState by collectLastValue(underTest.lockScreenState)
@@ -88,8 +79,21 @@
 
     @Test
     fun lockscreenState_whenGlanceableHubDisabled_returnsHidden() =
-        testScope.runTest {
-            kosmos.setCommunalV2Enabled(false)
+        kosmos.runTest {
+            setCommunalV2Enabled(false)
+            val lockScreenState by collectLastValue(underTest.lockScreenState)
+            runCurrent()
+
+            assertThat(lockScreenState)
+                .isEqualTo(KeyguardQuickAffordanceConfig.LockScreenState.Hidden)
+        }
+
+    @Test
+    fun lockscreenState_whenGlanceableHubNotAvailable_returnsHidden() =
+        kosmos.runTest {
+            // Hub is enabled, but not available.
+            setCommunalV2Enabled(true)
+            fakeKeyguardRepository.setKeyguardShowing(false)
             val lockScreenState by collectLastValue(underTest.lockScreenState)
             runCurrent()
 
@@ -99,8 +103,8 @@
 
     @Test
     fun pickerScreenState_whenGlanceableHubEnabled_returnsDefault() =
-        testScope.runTest {
-            kosmos.setCommunalV2Enabled(true)
+        kosmos.runTest {
+            setCommunalV2Enabled(true)
             runCurrent()
 
             assertThat(underTest.getPickerScreenState())
@@ -109,8 +113,8 @@
 
     @Test
     fun pickerScreenState_whenGlanceableHubDisabled_returnsDisabled() =
-        testScope.runTest {
-            kosmos.setCommunalV2Enabled(false)
+        kosmos.runTest {
+            setCommunalV2Enabled(false)
             runCurrent()
 
             assertThat(
@@ -122,7 +126,7 @@
     @Test
     @DisableFlags(Flags.FLAG_SCENE_CONTAINER)
     fun onTriggered_changesSceneToCommunal() =
-        testScope.runTest {
+        kosmos.runTest {
             underTest.onTriggered(expandable = null)
             runCurrent()
 
@@ -133,7 +137,7 @@
     @Test
     @EnableFlags(Flags.FLAG_SCENE_CONTAINER)
     fun testTransitionToGlanceableHub_sceneContainer() =
-        testScope.runTest {
+        kosmos.runTest {
             underTest.onTriggered(expandable = null)
             runCurrent()
 
@@ -145,11 +149,7 @@
         @JvmStatic
         @Parameters(name = "{0}")
         fun getParams(): List<FlagsParameterization> {
-            return FlagsParameterization.allCombinationsOf(
-                    Flags.FLAG_GLANCEABLE_HUB_SHORTCUT_BUTTON,
-                    Flags.FLAG_GLANCEABLE_HUB_V2,
-                )
-                .andSceneContainer()
+            return parameterizeSceneContainerFlag()
         }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceHapticViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceHapticViewModelTest.kt
new file mode 100644
index 0000000..18946f9
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceHapticViewModelTest.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.domain.interactor.keyguardQuickAffordanceHapticViewModelFactory
+import com.android.systemui.keyguard.domain.interactor.keyguardQuickAffordanceInteractor
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceHapticViewModel
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+class KeyguardQuickAffordanceHapticViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+    private val configKey = "$slotId::home"
+    private val keyguardQuickAffordanceInteractor = kosmos.keyguardQuickAffordanceInteractor
+    private val viewModelFlow =
+        MutableStateFlow(KeyguardQuickAffordanceViewModel(configKey = configKey, slotId = slotId))
+
+    private val underTest =
+        kosmos.keyguardQuickAffordanceHapticViewModelFactory.create(viewModelFlow)
+
+    @Test
+    fun whenLaunchingFromTriggeredResult_hapticStateIsLaunch() =
+        testScope.runTest {
+            // GIVEN that the result from triggering the affordance launched an activity or dialog
+            val hapticState by collectLastValue(underTest.quickAffordanceHapticState)
+            keyguardQuickAffordanceInteractor.setLaunchingFromTriggeredResult(
+                KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult(true, configKey)
+            )
+            runCurrent()
+
+            // THEN the haptic state indicates that a launch haptics must play
+            assertThat(hapticState)
+                .isEqualTo(KeyguardQuickAffordanceHapticViewModel.HapticState.LAUNCH)
+        }
+
+    @Test
+    fun whenNotLaunchFromTriggeredResult_hapticStateDoesNotEmit() =
+        testScope.runTest {
+            // GIVEN that the result from triggering the affordance did not launch an activity or
+            // dialog
+            val hapticState by collectLastValue(underTest.quickAffordanceHapticState)
+            keyguardQuickAffordanceInteractor.setLaunchingFromTriggeredResult(
+                KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult(false, configKey)
+            )
+            runCurrent()
+
+            // THEN there is no haptic state to play any feedback
+            assertThat(hapticState)
+                .isEqualTo(KeyguardQuickAffordanceHapticViewModel.HapticState.NO_HAPTICS)
+        }
+
+    @Test
+    fun onQuickAffordanceTogglesToActivated_hapticStateIsToggleOn() =
+        testScope.runTest {
+            // GIVEN that an affordance toggles from deactivated to activated
+            val hapticState by collectLastValue(underTest.quickAffordanceHapticState)
+            toggleQuickAffordance(on = true)
+
+            // THEN the haptic state reflects that a toggle on haptics should play
+            assertThat(hapticState)
+                .isEqualTo(KeyguardQuickAffordanceHapticViewModel.HapticState.TOGGLE_ON)
+        }
+
+    @Test
+    fun onQuickAffordanceTogglesToDeactivated_hapticStateIsToggleOff() =
+        testScope.runTest {
+            // GIVEN that an affordance toggles from activated to deactivated
+            val hapticState by collectLastValue(underTest.quickAffordanceHapticState)
+            toggleQuickAffordance(on = false)
+
+            // THEN the haptic state reflects that a toggle off haptics should play
+            assertThat(hapticState)
+                .isEqualTo(KeyguardQuickAffordanceHapticViewModel.HapticState.TOGGLE_OFF)
+        }
+
+    private fun TestScope.toggleQuickAffordance(on: Boolean) {
+        underTest.updateActivatedHistory(!on)
+        runCurrent()
+        underTest.updateActivatedHistory(on)
+        runCurrent()
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
index 4a422f0..8c54ca1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLegacySettingSyncerTest.kt
@@ -23,6 +23,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.kosmos.useUnconfinedTestDispatcher
@@ -84,6 +85,7 @@
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = FakeUserTracker(),
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         settings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
index 0f3e78b..bc2c2d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManagerTest.kt
@@ -20,13 +20,17 @@
 import android.content.Intent
 import android.content.SharedPreferences
 import android.content.pm.UserInfo
+import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.backup.BackupHelper
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.res.R
 import com.android.systemui.settings.FakeUserTracker
 import com.android.systemui.settings.UserFileManager
+import com.android.systemui.testKosmos
 import com.android.systemui.util.FakeSharedPreferences
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
@@ -54,6 +58,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class KeyguardQuickAffordanceLocalUserSelectionManagerTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
     @Mock private lateinit var userFileManager: UserFileManager
 
@@ -80,6 +85,7 @@
                 context = context,
                 userFileManager = userFileManager,
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
     }
@@ -110,27 +116,13 @@
         val affordanceId2 = "affordance2"
         val affordanceId3 = "affordance3"
 
-        underTest.setSelections(
-            slotId = slotId1,
-            affordanceIds = listOf(affordanceId1),
-        )
-        assertSelections(
-            affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId1),
-            ),
-        )
+        underTest.setSelections(slotId = slotId1, affordanceIds = listOf(affordanceId1))
+        assertSelections(affordanceIdsBySlotId.last(), mapOf(slotId1 to listOf(affordanceId1)))
 
-        underTest.setSelections(
-            slotId = slotId2,
-            affordanceIds = listOf(affordanceId2),
-        )
+        underTest.setSelections(slotId = slotId2, affordanceIds = listOf(affordanceId2))
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId1),
-                slotId2 to listOf(affordanceId2),
-            )
+            mapOf(slotId1 to listOf(affordanceId1), slotId2 to listOf(affordanceId2)),
         )
 
         underTest.setSelections(
@@ -139,34 +131,19 @@
         )
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId1, affordanceId3),
-                slotId2 to listOf(affordanceId2),
-            )
+            mapOf(slotId1 to listOf(affordanceId1, affordanceId3), slotId2 to listOf(affordanceId2)),
         )
 
-        underTest.setSelections(
-            slotId = slotId1,
-            affordanceIds = listOf(affordanceId3),
-        )
+        underTest.setSelections(slotId = slotId1, affordanceIds = listOf(affordanceId3))
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId3),
-                slotId2 to listOf(affordanceId2),
-            )
+            mapOf(slotId1 to listOf(affordanceId3), slotId2 to listOf(affordanceId2)),
         )
 
-        underTest.setSelections(
-            slotId = slotId2,
-            affordanceIds = listOf(),
-        )
+        underTest.setSelections(slotId = slotId2, affordanceIds = listOf())
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId3),
-                slotId2 to listOf(),
-            )
+            mapOf(slotId1 to listOf(affordanceId3), slotId2 to listOf()),
         )
 
         job.cancel()
@@ -174,10 +151,7 @@
 
     @Test
     fun remembersSelectionsByUser() = runTest {
-        overrideResource(
-            R.array.config_keyguardQuickAffordanceDefaults,
-            arrayOf<String>(),
-        )
+        overrideResource(R.array.config_keyguardQuickAffordanceDefaults, arrayOf<String>())
         val slot1 = "slot_1"
         val slot2 = "slot_2"
         val affordance1 = "affordance_1"
@@ -195,60 +169,28 @@
                 UserInfo(/* id= */ 0, "zero", /* flags= */ 0),
                 UserInfo(/* id= */ 1, "one", /* flags= */ 0),
             )
-        userTracker.set(
-            userInfos = userInfos,
-            selectedUserIndex = 0,
-        )
-        underTest.setSelections(
-            slotId = slot1,
-            affordanceIds = listOf(affordance1),
-        )
-        underTest.setSelections(
-            slotId = slot2,
-            affordanceIds = listOf(affordance2),
-        )
+        userTracker.set(userInfos = userInfos, selectedUserIndex = 0)
+        underTest.setSelections(slotId = slot1, affordanceIds = listOf(affordance1))
+        underTest.setSelections(slotId = slot2, affordanceIds = listOf(affordance2))
 
         // Switch to user 1
-        userTracker.set(
-            userInfos = userInfos,
-            selectedUserIndex = 1,
-        )
+        userTracker.set(userInfos = userInfos, selectedUserIndex = 1)
         // We never set selections on user 1, so it should be empty.
-        assertSelections(
-            observed = affordanceIdsBySlotId.last(),
-            expected = emptyMap(),
-        )
+        assertSelections(observed = affordanceIdsBySlotId.last(), expected = emptyMap())
         // Now, let's set selections on user 1.
-        underTest.setSelections(
-            slotId = slot1,
-            affordanceIds = listOf(affordance2),
-        )
-        underTest.setSelections(
-            slotId = slot2,
-            affordanceIds = listOf(affordance3),
-        )
+        underTest.setSelections(slotId = slot1, affordanceIds = listOf(affordance2))
+        underTest.setSelections(slotId = slot2, affordanceIds = listOf(affordance3))
         assertSelections(
             observed = affordanceIdsBySlotId.last(),
-            expected =
-                mapOf(
-                    slot1 to listOf(affordance2),
-                    slot2 to listOf(affordance3),
-                ),
+            expected = mapOf(slot1 to listOf(affordance2), slot2 to listOf(affordance3)),
         )
 
         // Switch back to user 0.
-        userTracker.set(
-            userInfos = userInfos,
-            selectedUserIndex = 0,
-        )
+        userTracker.set(userInfos = userInfos, selectedUserIndex = 0)
         // Assert that we still remember the old selections for user 0.
         assertSelections(
             observed = affordanceIdsBySlotId.last(),
-            expected =
-                mapOf(
-                    slot1 to listOf(affordance1),
-                    slot2 to listOf(affordance2),
-                ),
+            expected = mapOf(slot1 to listOf(affordance1), slot2 to listOf(affordance2)),
         )
 
         job.cancel()
@@ -276,10 +218,7 @@
 
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId1, affordanceId3),
-                slotId2 to listOf(affordanceId2),
-            ),
+            mapOf(slotId1 to listOf(affordanceId1, affordanceId3), slotId2 to listOf(affordanceId2)),
         )
 
         job.cancel()
@@ -308,10 +247,7 @@
         underTest.setSelections(slotId1, listOf(affordanceId2))
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(affordanceId2),
-                slotId2 to listOf(affordanceId2),
-            ),
+            mapOf(slotId1 to listOf(affordanceId2), slotId2 to listOf(affordanceId2)),
         )
 
         job.cancel()
@@ -340,10 +276,7 @@
         underTest.setSelections(slotId1, listOf())
         assertSelections(
             affordanceIdsBySlotId.last(),
-            mapOf(
-                slotId1 to listOf(),
-                slotId2 to listOf(affordanceId2),
-            ),
+            mapOf(slotId1 to listOf(), slotId2 to listOf(affordanceId2)),
         )
 
         job.cancel()
@@ -373,18 +306,36 @@
         overrideResource(R.bool.custom_lockscreen_shortcuts_enabled, false)
         overrideResource(
             R.array.config_keyguardQuickAffordanceDefaults,
-            arrayOf("leftTest:testShortcut1", "rightTest:testShortcut2")
+            arrayOf("leftTest:testShortcut1", "rightTest:testShortcut2"),
         )
 
         assertThat(underTest.getSelections())
             .isEqualTo(
-                mapOf(
-                    "leftTest" to listOf("testShortcut1"),
-                    "rightTest" to listOf("testShortcut2"),
-                )
+                mapOf("leftTest" to listOf("testShortcut1"), "rightTest" to listOf("testShortcut2"))
             )
     }
 
+    @EnableFlags(Flags.FLAG_GLANCEABLE_HUB_V2)
+    @Test
+    fun getSelections_returnsSelectionsIfHubV2Enabled() = runTest {
+        overrideResource(R.bool.custom_lockscreen_shortcuts_enabled, false)
+        overrideResource(com.android.internal.R.bool.config_glanceableHubEnabled, true)
+
+        overrideResource(R.array.config_keyguardQuickAffordanceDefaults, arrayOf<String>())
+        val affordanceIdsBySlotId = mutableListOf<Map<String, List<String>>>()
+        val job =
+            launch(UnconfinedTestDispatcher()) {
+                underTest.selections.toList(affordanceIdsBySlotId)
+            }
+        val slotId1 = "slot1"
+        val affordanceId1 = "affordance1"
+
+        underTest.setSelections(slotId = slotId1, affordanceIds = listOf(affordanceId1))
+        assertSelections(affordanceIdsBySlotId.last(), mapOf(slotId1 to listOf(affordanceId1)))
+
+        job.cancel()
+    }
+
     private fun assertSelections(
         observed: Map<String, List<String>>?,
         expected: Map<String, List<String>>,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
index b15352b..173b4e5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
@@ -49,14 +49,10 @@
 class MuteQuickAffordanceConfigTest : SysuiTestCase() {
 
     private lateinit var underTest: MuteQuickAffordanceConfig
-    @Mock
-    private lateinit var ringerModeTracker: RingerModeTracker
-    @Mock
-    private lateinit var audioManager: AudioManager
-    @Mock
-    private lateinit var userTracker: UserTracker
-    @Mock
-    private lateinit var userFileManager: UserFileManager
+    @Mock private lateinit var ringerModeTracker: RingerModeTracker
+    @Mock private lateinit var audioManager: AudioManager
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var userFileManager: UserFileManager
 
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testScope: TestScope
@@ -70,9 +66,12 @@
 
         whenever(userTracker.userContext).thenReturn(context)
         whenever(userFileManager.getSharedPreferences(any(), any(), any()))
-                .thenReturn(context.getSharedPreferences("mutequickaffordancetest", Context.MODE_PRIVATE))
+            .thenReturn(
+                context.getSharedPreferences("mutequickaffordancetest", Context.MODE_PRIVATE)
+            )
 
-        underTest = MuteQuickAffordanceConfig(
+        underTest =
+            MuteQuickAffordanceConfig(
                 context,
                 userTracker,
                 userFileManager,
@@ -81,64 +80,71 @@
                 testScope.backgroundScope,
                 testDispatcher,
                 testDispatcher,
-        )
+            )
     }
 
     @Test
-    fun pickerState_volumeFixed_notAvailable() = testScope.runTest {
-        //given
-        whenever(audioManager.isVolumeFixed).thenReturn(true)
+    fun pickerState_volumeFixed_notAvailable() =
+        testScope.runTest {
+            // given
+            whenever(audioManager.isVolumeFixed).thenReturn(true)
 
-        //when
-        val result = underTest.getPickerScreenState()
+            // when
+            val result = underTest.getPickerScreenState()
 
-        //then
-        assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice, result)
-    }
+            // then
+            assertEquals(
+                KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice,
+                result,
+            )
+        }
 
     @Test
-    fun pickerState_volumeNotFixed_available() = testScope.runTest {
-        //given
-        whenever(audioManager.isVolumeFixed).thenReturn(false)
+    fun pickerState_volumeNotFixed_available() =
+        testScope.runTest {
+            // given
+            whenever(audioManager.isVolumeFixed).thenReturn(false)
 
-        //when
-        val result = underTest.getPickerScreenState()
+            // when
+            val result = underTest.getPickerScreenState()
 
-        //then
-        assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default(), result)
-    }
+            // then
+            assertEquals(KeyguardQuickAffordanceConfig.PickerScreenState.Default(), result)
+        }
 
     @Test
-    fun triggered_stateWasPreviouslyNORMAL_currentlySILENT_moveToPreviousState() = testScope.runTest {
-        //given
-        val ringerModeCapture = argumentCaptor<Int>()
-        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
-        underTest.onTriggered(null)
-        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_SILENT)
+    fun triggered_stateWasPreviouslyNORMAL_currentlySILENT_moveToPreviousState() =
+        testScope.runTest {
+            // given
+            val ringerModeCapture = argumentCaptor<Int>()
+            whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
+            underTest.onTriggered(null)
+            whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_SILENT)
 
-        //when
-        val result = underTest.onTriggered(null)
-        runCurrent()
-        verify(audioManager, times(2)).ringerModeInternal = ringerModeCapture.capture()
+            // when
+            val result = underTest.onTriggered(null)
+            runCurrent()
+            verify(audioManager, times(2)).ringerModeInternal = ringerModeCapture.capture()
 
-        //then
-        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
-        assertEquals(AudioManager.RINGER_MODE_NORMAL, ringerModeCapture.value)
-    }
+            // then
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
+            assertEquals(AudioManager.RINGER_MODE_NORMAL, ringerModeCapture.value)
+        }
 
     @Test
-    fun triggered_stateIsNotSILENT_moveToSILENTringer() = testScope.runTest {
-        //given
-        val ringerModeCapture = argumentCaptor<Int>()
-        whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
+    fun triggered_stateIsNotSILENT_moveToSILENTringer() =
+        testScope.runTest {
+            // given
+            val ringerModeCapture = argumentCaptor<Int>()
+            whenever(audioManager.ringerModeInternal).thenReturn(AudioManager.RINGER_MODE_NORMAL)
 
-        //when
-        val result = underTest.onTriggered(null)
-        runCurrent()
-        verify(audioManager).ringerModeInternal = ringerModeCapture.capture()
+            // when
+            val result = underTest.onTriggered(null)
+            runCurrent()
+            verify(audioManager).ringerModeInternal = ringerModeCapture.capture()
 
-        //then
-        assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled, result)
-        assertEquals(AudioManager.RINGER_MODE_SILENT, ringerModeCapture.value)
-    }
-}
\ No newline at end of file
+            // then
+            assertEquals(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false), result)
+            assertEquals(AudioManager.RINGER_MODE_SILENT, ringerModeCapture.value)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
index e9b36b8..9bdc363 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfigTest.kt
@@ -88,9 +88,7 @@
                     Icon.Loaded(
                         drawable = ICON,
                         contentDescription =
-                            ContentDescription.Resource(
-                                res = R.string.accessibility_wallet_button,
-                            ),
+                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                     )
                 )
         }
@@ -118,9 +116,7 @@
                     Icon.Loaded(
                         drawable = ICON,
                         contentDescription =
-                            ContentDescription.Resource(
-                                res = R.string.accessibility_wallet_button,
-                            ),
+                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
                     )
                 )
         }
@@ -163,13 +159,9 @@
         }
 
         assertThat(underTest.onTriggered(expandable))
-            .isEqualTo(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled)
+            .isEqualTo(KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(true))
         verify(walletController)
-            .startQuickAccessUiIntent(
-                activityStarter,
-                animationController,
-                /* hasCard= */ true,
-            )
+            .startQuickAccessUiIntent(activityStarter, animationController, /* hasCard= */ true)
     }
 
     @Test
@@ -184,9 +176,7 @@
     @Test
     fun getPickerScreenState_unavailable() =
         testScope.runTest {
-            setUpState(
-                isWalletServiceAvailable = false,
-            )
+            setUpState(isWalletServiceAvailable = false)
 
             assertThat(underTest.getPickerScreenState())
                 .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
@@ -195,9 +185,7 @@
     @Test
     fun getPickerScreenState_disabledWhenTheFeatureIsNotEnabled() =
         testScope.runTest {
-            setUpState(
-                isWalletFeatureAvailable = false,
-            )
+            setUpState(isWalletFeatureAvailable = false)
 
             assertThat(underTest.getPickerScreenState())
                 .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java)
@@ -206,9 +194,7 @@
     @Test
     fun getPickerScreenState_disabledWhenThereIsNoCard() =
         testScope.runTest {
-            setUpState(
-                hasSelectedCard = false,
-            )
+            setUpState(hasSelectedCard = false)
 
             assertThat(underTest.getPickerScreenState())
                 .isInstanceOf(KeyguardQuickAffordanceConfig.PickerScreenState.Disabled::class.java)
@@ -219,7 +205,7 @@
         isWalletServiceAvailable: Boolean = true,
         isWalletQuerySuccessful: Boolean = true,
         hasSelectedCard: Boolean = true,
-        cardType: Int = WalletCard.CARD_TYPE_UNKNOWN
+        cardType: Int = WalletCard.CARD_TYPE_UNKNOWN,
     ) {
         val walletClient: QuickAccessWalletClient = mock()
         whenever(walletClient.tileIcon).thenReturn(ICON)
@@ -242,11 +228,11 @@
                                             /*cardType= */ cardType,
                                             /*cardImage= */ mock(),
                                             /*contentDescription=  */ CARD_DESCRIPTION,
-                                            /*pendingIntent= */ mock()
+                                            /*pendingIntent= */ mock(),
                                         )
                                         .build()
                                 ),
-                                0
+                                0,
                             )
                         } else {
                             GetWalletCardsResponse(emptyList(), 0)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
index 1582e47..a101818 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardQuickAffordanceRepositoryTest.kt
@@ -22,6 +22,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceProviderClientFactory
@@ -84,16 +85,11 @@
                 context = context,
                 userFileManager =
                     mock<UserFileManager>().apply {
-                        whenever(
-                                getSharedPreferences(
-                                    anyString(),
-                                    anyInt(),
-                                    anyInt(),
-                                )
-                            )
+                        whenever(getSharedPreferences(anyString(), anyInt(), anyInt()))
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         client1 = FakeCustomizationProviderClient()
@@ -103,9 +99,8 @@
                 scope = testScope.backgroundScope,
                 userTracker = userTracker,
                 clientFactory =
-                    FakeKeyguardQuickAffordanceProviderClientFactory(
-                        userTracker,
-                    ) { selectedUserId ->
+                    FakeKeyguardQuickAffordanceProviderClientFactory(userTracker) { selectedUserId
+                        ->
                         when (selectedUserId) {
                             SECONDARY_USER_1 -> client1
                             SECONDARY_USER_2 -> client2
@@ -115,10 +110,7 @@
                 userHandle = UserHandle.SYSTEM,
             )
 
-        overrideResource(
-            R.array.config_keyguardQuickAffordanceDefaults,
-            arrayOf<String>(),
-        )
+        overrideResource(R.array.config_keyguardQuickAffordanceDefaults, arrayOf<String>())
 
         underTest =
             KeyguardQuickAffordanceRepository(
@@ -155,30 +147,19 @@
             val slotId2 = "slot2"
 
             underTest.setSelections(slotId1, listOf(config1.key))
-            assertSelections(
-                configsBySlotId(),
-                mapOf(
-                    slotId1 to listOf(config1),
-                ),
-            )
+            assertSelections(configsBySlotId(), mapOf(slotId1 to listOf(config1)))
 
             underTest.setSelections(slotId2, listOf(config2.key))
             assertSelections(
                 configsBySlotId(),
-                mapOf(
-                    slotId1 to listOf(config1),
-                    slotId2 to listOf(config2),
-                ),
+                mapOf(slotId1 to listOf(config1), slotId2 to listOf(config2)),
             )
 
             underTest.setSelections(slotId1, emptyList())
             underTest.setSelections(slotId2, listOf(config1.key))
             assertSelections(
                 configsBySlotId(),
-                mapOf(
-                    slotId1 to emptyList(),
-                    slotId2 to listOf(config1),
-                ),
+                mapOf(slotId1 to emptyList(), slotId2 to listOf(config1)),
             )
         }
 
@@ -209,28 +190,15 @@
         val slot3 = "slot3"
         context.orCreateTestableResources.addOverride(
             R.array.config_keyguardQuickAffordanceSlots,
-            arrayOf(
-                "$slot1:2",
-                "$slot2:4",
-                "$slot3:5",
-            ),
+            arrayOf("$slot1:2", "$slot2:4", "$slot3:5"),
         )
 
         assertThat(underTest.getSlotPickerRepresentations())
             .isEqualTo(
                 listOf(
-                    KeyguardSlotPickerRepresentation(
-                        id = slot1,
-                        maxSelectedAffordances = 2,
-                    ),
-                    KeyguardSlotPickerRepresentation(
-                        id = slot2,
-                        maxSelectedAffordances = 4,
-                    ),
-                    KeyguardSlotPickerRepresentation(
-                        id = slot3,
-                        maxSelectedAffordances = 5,
-                    ),
+                    KeyguardSlotPickerRepresentation(id = slot1, maxSelectedAffordances = 2),
+                    KeyguardSlotPickerRepresentation(id = slot2, maxSelectedAffordances = 4),
+                    KeyguardSlotPickerRepresentation(id = slot3, maxSelectedAffordances = 5),
                 )
             )
     }
@@ -243,28 +211,15 @@
         val slot3 = "slot3"
         context.orCreateTestableResources.addOverride(
             R.array.config_keyguardQuickAffordanceSlots,
-            arrayOf(
-                "$slot1:2",
-                "$slot2:4",
-                "$slot3:5",
-            ),
+            arrayOf("$slot1:2", "$slot2:4", "$slot3:5"),
         )
 
         assertThat(underTest.getSlotPickerRepresentations())
             .isEqualTo(
                 listOf(
-                    KeyguardSlotPickerRepresentation(
-                        id = slot3,
-                        maxSelectedAffordances = 5,
-                    ),
-                    KeyguardSlotPickerRepresentation(
-                        id = slot2,
-                        maxSelectedAffordances = 4,
-                    ),
-                    KeyguardSlotPickerRepresentation(
-                        id = slot1,
-                        maxSelectedAffordances = 2,
-                    ),
+                    KeyguardSlotPickerRepresentation(id = slot3, maxSelectedAffordances = 5),
+                    KeyguardSlotPickerRepresentation(id = slot2, maxSelectedAffordances = 4),
+                    KeyguardSlotPickerRepresentation(id = slot1, maxSelectedAffordances = 2),
                 )
             )
     }
@@ -275,21 +230,9 @@
             userTracker.set(
                 userInfos =
                     listOf(
-                        UserInfo(
-                            UserHandle.USER_SYSTEM,
-                            "Primary",
-                            /* flags= */ 0,
-                        ),
-                        UserInfo(
-                            SECONDARY_USER_1,
-                            "Secondary 1",
-                            /* flags= */ 0,
-                        ),
-                        UserInfo(
-                            SECONDARY_USER_2,
-                            "Secondary 2",
-                            /* flags= */ 0,
-                        ),
+                        UserInfo(UserHandle.USER_SYSTEM, "Primary", /* flags= */ 0),
+                        UserInfo(SECONDARY_USER_1, "Secondary 1", /* flags= */ 0),
+                        UserInfo(SECONDARY_USER_2, "Secondary 2", /* flags= */ 0),
                     ),
                 selectedUserIndex = 2,
             )
@@ -302,12 +245,7 @@
             assertSelections(
                 observed = observed(),
                 expected =
-                    mapOf(
-                        KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to
-                            listOf(
-                                config2,
-                            ),
-                    )
+                    mapOf(KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START to listOf(config2)),
             )
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
index 46d1ebe..fe9da0d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.dock.DockManager
@@ -147,6 +148,7 @@
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         val remoteUserSelectionManager =
@@ -196,6 +198,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = kosmos.testDispatcher,
                 appContext = context,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 sceneInteractor = { kosmos.sceneInteractor },
             )
         kosmos.keyguardQuickAffordanceInteractor = underTest
@@ -764,6 +767,28 @@
             assertThat(launchingAffordance).isFalse()
         }
 
+    @Test
+    fun onQuickAffordanceTriggered_updatesLaunchingFromTriggeredResult() =
+        testScope.runTest {
+            // WHEN selecting and triggering a quick affordance at a slot
+            val key = homeControls.key
+            val slot = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+            val encodedKey = "$slot::$key"
+            val actionLaunched = true
+            homeControls.onTriggeredResult =
+                KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(actionLaunched)
+            underTest.select(slot, key)
+            runCurrent()
+            underTest.onQuickAffordanceTriggered(encodedKey, expandable = null, slot)
+
+            // THEN the latest triggered result shows that an action launched for the same key and
+            // slot
+            val launchingFromTriggeredResult by
+                collectLastValue(underTest.launchingFromTriggeredResult)
+            assertThat(launchingFromTriggeredResult?.launched).isEqualTo(actionLaunched)
+            assertThat(launchingFromTriggeredResult?.configKey).isEqualTo(encodedKey)
+        }
+
     companion object {
         private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337
         private val ICON: Icon =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractorTest.kt
index 28ac169..16f02c5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractorTest.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryFaceAuthInteractor
 import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
-import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -93,9 +92,7 @@
         testScope.runTest {
             val isEnabled = collectLastValue(underTest.isLongPressHandlingEnabled)
             KeyguardState.values().forEach { keyguardState ->
-                setUpState(
-                    keyguardState = keyguardState,
-                )
+                setUpState(keyguardState = keyguardState)
 
                 if (keyguardState == KeyguardState.LOCKSCREEN) {
                     assertThat(isEnabled()).isTrue()
@@ -110,10 +107,7 @@
         testScope.runTest {
             val isEnabled = collectLastValue(underTest.isLongPressHandlingEnabled)
             KeyguardState.values().forEach { keyguardState ->
-                setUpState(
-                    keyguardState = keyguardState,
-                    isQuickSettingsVisible = true,
-                )
+                setUpState(keyguardState = keyguardState, isQuickSettingsVisible = true)
 
                 assertThat(isEnabled()).isFalse()
             }
@@ -290,22 +284,19 @@
             keyguardTransitionRepository.sendTransitionSteps(
                 from = KeyguardState.LOCKSCREEN,
                 to = KeyguardState.GONE,
-                testScope
+                testScope,
             )
             assertThat(isMenuVisible).isFalse()
 
             keyguardTransitionRepository.sendTransitionSteps(
                 from = KeyguardState.GONE,
                 to = KeyguardState.LOCKSCREEN,
-                testScope
+                testScope,
             )
             assertThat(isMenuVisible).isFalse()
         }
 
-    private suspend fun createUnderTest(
-        isLongPressFeatureEnabled: Boolean = true,
-        isRevampedWppFeatureEnabled: Boolean = true,
-    ) {
+    private suspend fun createUnderTest(isRevampedWppFeatureEnabled: Boolean = true) {
         // This needs to be re-created for each test outside of kosmos since the flag values are
         // read during initialization to set up flows. Maybe there is a better way to handle that.
         underTest =
@@ -315,10 +306,7 @@
                 transitionInteractor = kosmos.keyguardTransitionInteractor,
                 repository = keyguardRepository,
                 logger = logger,
-                featureFlags =
-                    kosmos.fakeFeatureFlagsClassic.apply {
-                        set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, isLongPressFeatureEnabled)
-                    },
+                featureFlags = kosmos.fakeFeatureFlagsClassic,
                 broadcastDispatcher = fakeBroadcastDispatcher,
                 accessibilityManager = kosmos.accessibilityManagerWrapper,
                 pulsingGestureListener = kosmos.pulsingGestureListener,
@@ -334,7 +322,7 @@
         keyguardTransitionRepository.sendTransitionSteps(
             from = KeyguardState.AOD,
             to = keyguardState,
-            testScope = testScope
+            testScope = testScope,
         )
         keyguardRepository.setQuickSettingsVisible(isVisible = isQuickSettingsVisible)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt
index ad5eeab..26fe379 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractorTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.data.repository.sceneContainerRepository
+import com.android.systemui.scene.shared.model.Overlays
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -118,6 +119,50 @@
             )
         }
 
+    /** STL: Ls -> overlay, then settle with Idle(overlay). */
+    @Test
+    fun transition_overlay_from_ls_scene_end_in_gone() =
+        testScope.runTest {
+            sceneTransitions.value =
+                ObservableTransitionState.Transition.ShowOrHideOverlay(
+                    overlay = Overlays.NotificationsShade,
+                    fromContent = Scenes.Lockscreen,
+                    toContent = Overlays.NotificationsShade,
+                    currentScene = Scenes.Lockscreen,
+                    currentOverlays = flowOf(emptySet()),
+                    progress,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
+                    previewProgress = flowOf(0f),
+                    isInPreviewStage = flowOf(false),
+                )
+
+            val currentStep by collectLastValue(kosmos.realKeyguardTransitionRepository.transitions)
+            assertTransition(
+                step = currentStep!!,
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.UNDEFINED,
+                state = TransitionState.RUNNING,
+                progress = 0f,
+            )
+
+            progress.value = 0.4f
+            assertTransition(step = currentStep!!, state = TransitionState.RUNNING, progress = 0.4f)
+
+            sceneTransitions.value =
+                ObservableTransitionState.Idle(
+                    Scenes.Lockscreen,
+                    setOf(Overlays.NotificationsShade),
+                )
+            assertTransition(
+                step = currentStep!!,
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.UNDEFINED,
+                state = TransitionState.FINISHED,
+                progress = 1f,
+            )
+        }
+
     /**
      * STL: Ls -> Gone, then settle with Idle(Ls). KTF in this scenario needs to invert the
      * transition LS -> UNDEFINED to UNDEFINED -> LS as there is no mechanism in KTF to
@@ -259,6 +304,47 @@
             )
         }
 
+    /** STL: Ls with overlay, then settle with Idle(Ls). */
+    @Test
+    fun transition_overlay_to_ls_scene_end_in_ls() =
+        testScope.runTest {
+            val currentStep by collectLastValue(kosmos.realKeyguardTransitionRepository.transitions)
+            sceneTransitions.value =
+                ObservableTransitionState.Transition.ShowOrHideOverlay(
+                    overlay = Overlays.NotificationsShade,
+                    fromContent = Overlays.NotificationsShade,
+                    toContent = Scenes.Lockscreen,
+                    currentScene = Scenes.Lockscreen,
+                    currentOverlays = flowOf(setOf(Overlays.NotificationsShade)),
+                    progress,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
+                    previewProgress = flowOf(0f),
+                    isInPreviewStage = flowOf(false),
+                )
+
+            assertTransition(
+                step = currentStep!!,
+                from = KeyguardState.UNDEFINED,
+                to = KeyguardState.LOCKSCREEN,
+                state = TransitionState.RUNNING,
+                progress = 0f,
+            )
+
+            progress.value = 0.4f
+            assertTransition(step = currentStep!!, state = TransitionState.RUNNING, progress = 0.4f)
+
+            sceneTransitions.value = ObservableTransitionState.Idle(Scenes.Lockscreen)
+
+            assertTransition(
+                step = currentStep!!,
+                from = KeyguardState.UNDEFINED,
+                to = KeyguardState.LOCKSCREEN,
+                state = TransitionState.FINISHED,
+                progress = 1f,
+            )
+        }
+
     /** STL: Gone -> Ls (AOD), will transition to AOD once */
     @Test
     fun transition_to_ls_scene_with_changed_next_scene_is_respected_just_once() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
index 040d3b8..4e3d18c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinderTest.kt
@@ -21,8 +21,6 @@
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.keyguard.KeyguardClockSwitch.SMALL
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
@@ -80,6 +78,7 @@
         verify(rootView).addView(smallClockView)
         verify(rootView).addView(largeClockView)
     }
+
     @Test
     fun addClockViewsToBurnInLayer_LargeWeatherClock() {
         setupWeatherClock()
@@ -110,7 +109,7 @@
                 name = "",
                 description = "",
                 useAlternateSmartspaceAODTransition = true,
-                useCustomClockScene = true
+                useCustomClockScene = true,
             )
         whenever(clock.config).thenReturn(clockConfig)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
index 9fab0d90..67a4332 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt
@@ -37,7 +37,6 @@
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
-import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultUdfpsAccessibilityOverlaySection
 import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSliceViewSection
 import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
@@ -67,7 +66,6 @@
     @Mock private lateinit var defaultShortcutsSection: DefaultShortcutsSection
     @Mock private lateinit var defaultAmbientIndicationAreaSection: Optional<KeyguardSection>
     @Mock private lateinit var defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection
-    @Mock private lateinit var defaultStatusViewSection: DefaultStatusViewSection
     @Mock private lateinit var defaultStatusBarViewSection: DefaultStatusBarSection
     @Mock private lateinit var defaultNSSLSection: DefaultNotificationStackScrollLayoutSection
     @Mock private lateinit var splitShadeGuidelines: SplitShadeGuidelines
@@ -79,6 +77,7 @@
     @Mock private lateinit var keyguardSliceViewSection: KeyguardSliceViewSection
     @Mock
     private lateinit var udfpsAccessibilityOverlaySection: DefaultUdfpsAccessibilityOverlaySection
+
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
@@ -91,7 +90,6 @@
                 defaultShortcutsSection,
                 defaultAmbientIndicationAreaSection,
                 defaultSettingsPopupMenuSection,
-                defaultStatusViewSection,
                 defaultStatusBarViewSection,
                 defaultNSSLSection,
                 aodNotificationIconsSection,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
index c0db95f..7706c50 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSectionTest.kt
@@ -17,7 +17,6 @@
 
 package com.android.systemui.keyguard.ui.view.layout.sections
 
-import android.platform.test.annotations.EnableFlags
 import android.view.View
 import android.widget.LinearLayout
 import androidx.constraintlayout.widget.ConstraintLayout
@@ -26,7 +25,6 @@
 import androidx.constraintlayout.widget.ConstraintSet.VISIBLE
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.customization.R as customR
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
@@ -50,7 +48,6 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
-@EnableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
 class SmartspaceSectionTest : SysuiTestCase() {
     private lateinit var underTest: SmartspaceSection
     @Mock private lateinit var keyguardClockViewModel: KeyguardClockViewModel
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
index 70d7a5f..feaf06a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelTest.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.testKosmos
@@ -79,8 +79,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0f, 0f, 0.1f, 0.2f, 0.3f, 1f),
-                startValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 checkInterpolatedValues = false,
                 transitionFactory = ::step,
                 actualValuesProvider = { values },
@@ -95,8 +95,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0f, 0f, 0.1f, 0.2f, 0.3f, 1f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.minBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 transitionFactory = ::step,
                 actualValuesProvider = { values },
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelTest.kt
deleted file mode 100644
index 9e69601..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelTest.kt
+++ /dev/null
@@ -1,269 +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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.Flags
-import com.android.systemui.Flags as AConfigFlags
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.DisableSceneContainer
-import com.android.systemui.flags.EnableSceneContainer
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.TransitionState
-import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.data.repository.Idle
-import com.android.systemui.scene.data.repository.Transition
-import com.android.systemui.scene.data.repository.setSceneTransition
-import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.testKosmos
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class AodAlphaViewModelTest : SysuiTestCase() {
-
-    @Mock private lateinit var goneToAodTransitionViewModel: GoneToAodTransitionViewModel
-
-    private val kosmos = testKosmos()
-    private val testScope = kosmos.testScope
-    private val keyguardRepository = kosmos.fakeKeyguardRepository
-    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
-
-    private lateinit var underTest: AodAlphaViewModel
-
-    private val enterFromTopAnimationAlpha = MutableStateFlow(0f)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-        whenever(goneToAodTransitionViewModel.enterFromTopAnimationAlpha)
-            .thenReturn(enterFromTopAnimationAlpha)
-        kosmos.goneToAodTransitionViewModel = goneToAodTransitionViewModel
-
-        underTest = kosmos.aodAlphaViewModel
-    }
-
-    @Test
-    @DisableSceneContainer
-    @DisableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun alpha_WhenNotGone_clockMigrationFlagIsOff_emitsKeyguardAlpha() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.AOD,
-                to = KeyguardState.LOCKSCREEN,
-                testScope = testScope,
-            )
-
-            keyguardRepository.setKeyguardAlpha(0.5f)
-            assertThat(alpha).isEqualTo(0.5f)
-
-            keyguardRepository.setKeyguardAlpha(0.8f)
-            assertThat(alpha).isEqualTo(0.8f)
-        }
-
-    @Test
-    @DisableSceneContainer
-    fun alpha_WhenGoneToAod() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.AOD,
-                to = KeyguardState.GONE,
-                testScope = testScope,
-            )
-            assertThat(alpha).isEqualTo(0f)
-
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.GONE,
-                to = KeyguardState.AOD,
-                testScope = testScope,
-            )
-            enterFromTopAnimationAlpha.value = 0.5f
-            assertThat(alpha).isEqualTo(0.5f)
-
-            enterFromTopAnimationAlpha.value = 1f
-            assertThat(alpha).isEqualTo(1f)
-        }
-
-    @Test
-    @EnableSceneContainer
-    fun alpha_WhenGoneToAod_scene_container() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.AOD,
-                to = KeyguardState.UNDEFINED,
-                testScope = testScope,
-            )
-            kosmos.setSceneTransition(Idle(Scenes.Gone))
-            assertThat(alpha).isEqualTo(0f)
-
-            kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.UNDEFINED,
-                to = KeyguardState.AOD,
-                testScope = testScope,
-            )
-            enterFromTopAnimationAlpha.value = 0.5f
-            assertThat(alpha).isEqualTo(0.5f)
-
-            enterFromTopAnimationAlpha.value = 1f
-            assertThat(alpha).isEqualTo(1f)
-        }
-
-    @Test
-    @DisableSceneContainer
-    fun alpha_WhenGoneToDozing() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.AOD,
-                to = KeyguardState.GONE,
-                testScope = testScope,
-            )
-            assertThat(alpha).isEqualTo(0f)
-
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.GONE,
-                to = KeyguardState.DOZING,
-                testScope = testScope,
-            )
-            assertThat(alpha).isEqualTo(1f)
-        }
-
-    @Test
-    @EnableSceneContainer
-    fun alpha_WhenGoneToDozing_scene_container() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            kosmos.setSceneTransition(Idle(Scenes.Gone))
-            assertThat(alpha).isEqualTo(0f)
-
-            kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.UNDEFINED,
-                to = KeyguardState.DOZING,
-                testScope = testScope,
-            )
-            assertThat(alpha).isEqualTo(1f)
-        }
-
-    @Test
-    @DisableSceneContainer
-    @EnableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun alpha_whenGone_equalsZero() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.LOCKSCREEN,
-                    to = KeyguardState.GONE,
-                    transitionState = TransitionState.STARTED,
-                )
-            )
-            assertThat(alpha).isNull()
-
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.LOCKSCREEN,
-                    to = KeyguardState.GONE,
-                    transitionState = TransitionState.RUNNING,
-                    value = 0.5f,
-                )
-            )
-            assertThat(alpha).isNull()
-
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.LOCKSCREEN,
-                    to = KeyguardState.GONE,
-                    transitionState = TransitionState.RUNNING,
-                    value = 1f,
-                )
-            )
-            assertThat(alpha).isEqualTo(0f)
-        }
-
-    @Test
-    @DisableSceneContainer
-    fun enterFromTopAlpha() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.GONE,
-                    to = KeyguardState.AOD,
-                    transitionState = TransitionState.STARTED,
-                )
-            )
-
-            enterFromTopAnimationAlpha.value = 0.2f
-            assertThat(alpha).isEqualTo(0.2f)
-
-            enterFromTopAnimationAlpha.value = 1f
-            assertThat(alpha).isEqualTo(1f)
-        }
-
-    @Test
-    @EnableSceneContainer
-    fun enterFromTopAlpha_scene_container() =
-        testScope.runTest {
-            val alpha by collectLastValue(underTest.alpha)
-
-            kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.UNDEFINED,
-                    to = KeyguardState.AOD,
-                    transitionState = TransitionState.STARTED,
-                )
-            )
-
-            enterFromTopAnimationAlpha.value = 0.2f
-            assertThat(alpha).isEqualTo(0.2f)
-
-            enterFromTopAnimationAlpha.value = 1f
-            assertThat(alpha).isEqualTo(1f)
-        }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
index 0e3b03f..be504cc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModelTest.kt
@@ -18,11 +18,8 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags as AConfigFlags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.DisableSceneContainer
@@ -75,7 +72,6 @@
     private val burnInFlow = MutableStateFlow(BurnInModel())
 
     @Before
-    @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     @DisableSceneContainer
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -219,50 +215,6 @@
         }
 
     @Test
-    @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun translationAndScale_whenFullyDozing_MigrationFlagOff_staysOutOfTopInset() =
-        testScope.runTest {
-            underTest.updateBurnInParams(burnInParameters.copy(minViewY = 100, topInset = 80))
-            val movement by collectLastValue(underTest.movement)
-            assertThat(movement?.translationX).isEqualTo(0)
-
-            // Set to dozing (on AOD)
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.GONE,
-                    to = KeyguardState.AOD,
-                    value = 1f,
-                    transitionState = TransitionState.FINISHED,
-                ),
-                validateStep = false,
-            )
-
-            // Trigger a change to the burn-in model
-            burnInFlow.value = BurnInModel(translationX = 20, translationY = -30, scale = 0.5f)
-            assertThat(movement?.translationX).isEqualTo(20)
-            // -20 instead of -30, due to inset of 80
-            assertThat(movement?.translationY).isEqualTo(-20)
-            assertThat(movement?.scale).isEqualTo(0.5f)
-            assertThat(movement?.scaleClockOnly).isEqualTo(true)
-
-            // Set to the beginning of GONE->AOD transition
-            keyguardTransitionRepository.sendTransitionStep(
-                TransitionStep(
-                    from = KeyguardState.GONE,
-                    to = KeyguardState.AOD,
-                    value = 0f,
-                    transitionState = TransitionState.STARTED,
-                ),
-                validateStep = false,
-            )
-            assertThat(movement?.translationX).isEqualTo(0)
-            assertThat(movement?.translationY).isEqualTo(0)
-            assertThat(movement?.scale).isEqualTo(1f)
-            assertThat(movement?.scaleClockOnly).isEqualTo(true)
-        }
-
-    @Test
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun translationAndScale_whenFullyDozing_MigrationFlagOn_staysOutOfTopInset() =
         testScope.runTest {
             underTest.updateBurnInParams(burnInParameters.copy(minViewY = 100, topInset = 80))
@@ -334,7 +286,6 @@
 
     @Test
     @DisableSceneContainer
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun translationAndScale_sceneContainerOff_weatherLargeClock() =
         testBurnInViewModelForClocks(
             isSmallClock = false,
@@ -344,7 +295,6 @@
 
     @Test
     @DisableSceneContainer
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun translationAndScale_sceneContainerOff_weatherSmallClock() =
         testBurnInViewModelForClocks(
             isSmallClock = true,
@@ -354,7 +304,6 @@
 
     @Test
     @DisableSceneContainer
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun translationAndScale_sceneContainerOff_nonWeatherLargeClock() =
         testBurnInViewModelForClocks(
             isSmallClock = false,
@@ -364,7 +313,6 @@
 
     @Test
     @DisableSceneContainer
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun translationAndScale_sceneContainerOff_nonWeatherSmallClock() =
         testBurnInViewModelForClocks(
             isSmallClock = true,
@@ -373,7 +321,6 @@
         )
 
     @Test
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     @EnableSceneContainer
     fun translationAndScale_sceneContainerOn_weatherLargeClock() =
         testBurnInViewModelForClocks(
@@ -383,7 +330,6 @@
         )
 
     @Test
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     @EnableSceneContainer
     fun translationAndScale_sceneContainerOn_weatherSmallClock() =
         testBurnInViewModelForClocks(
@@ -393,7 +339,6 @@
         )
 
     @Test
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     @EnableSceneContainer
     fun translationAndScale_sceneContainerOn_nonWeatherLargeClock() =
         testBurnInViewModelForClocks(
@@ -403,7 +348,6 @@
         )
 
     @Test
-    @EnableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     @EnableSceneContainer
     @Ignore("b/367659687")
     fun translationAndScale_sceneContainerOn_nonWeatherSmallClock() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModelTest.kt
index 0f239e8..4936f85 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModelTest.kt
@@ -21,7 +21,7 @@
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -44,8 +44,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.0f, 0.3f, 0.4f, 0.5f, 1.0f),
-                startValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 transitionFactory = { value, state ->
                     TransitionStep(
                         from = KeyguardState.AOD,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerWindowBlurTestUtilKosmos.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerWindowBlurTestUtilKosmos.kt
index c3f0deb..cde8531 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerWindowBlurTestUtilKosmos.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/BouncerWindowBlurTestUtilKosmos.kt
@@ -70,6 +70,7 @@
         if (checkInterpolatedValues) {
             assertThat(actualValuesProvider.invoke())
                 .containsExactly(*transitionProgress.map(interpolationFunction).toTypedArray())
+                .inOrder()
         } else {
             assertThat(actualValuesProvider.invoke()).contains(endValue)
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt
index 7a68d4e..0d48750 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelTest.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -78,8 +78,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.minBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
index 242ee3a..bd892d5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModelTest.kt
@@ -16,11 +16,8 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.ui.domain.interactor.configurationInteractor
 import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository
@@ -45,18 +42,14 @@
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
-import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.mock
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4
-import platform.test.runner.parameterized.Parameters
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@RunWith(ParameterizedAndroidJunit4::class)
-class KeyguardIndicationAreaViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
+class KeyguardIndicationAreaViewModelTest() : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private lateinit var underTest: KeyguardIndicationAreaViewModel
@@ -75,11 +68,6 @@
                 slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
             )
         )
-    private val alphaFlow = MutableStateFlow(1f)
-
-    init {
-        mSetFlagsRule.setFlagsParameterization(flags)
-    }
 
     @Before
     fun setUp() {
@@ -106,47 +94,11 @@
                 keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
                 backgroundDispatcher = kosmos.testDispatcher,
                 communalSceneInteractor = kosmos.communalSceneInteractor,
-                mainDispatcher = kosmos.testDispatcher
+                mainDispatcher = kosmos.testDispatcher,
             )
     }
 
     @Test
-    fun isIndicationAreaPadded() =
-        testScope.runTest {
-            keyguardRepository.setKeyguardShowing(true)
-            val isIndicationAreaPadded by collectLastValue(underTest.isIndicationAreaPadded)
-
-            assertThat(isIndicationAreaPadded).isFalse()
-            startButtonFlow.value = startButtonFlow.value.copy(isVisible = true)
-            assertThat(isIndicationAreaPadded).isTrue()
-            endButtonFlow.value = endButtonFlow.value.copy(isVisible = true)
-            assertThat(isIndicationAreaPadded).isTrue()
-            startButtonFlow.value = startButtonFlow.value.copy(isVisible = false)
-            assertThat(isIndicationAreaPadded).isTrue()
-            endButtonFlow.value = endButtonFlow.value.copy(isVisible = false)
-            assertThat(isIndicationAreaPadded).isFalse()
-        }
-
-    @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun indicationAreaTranslationY() =
-        testScope.runTest {
-            val translationY by
-                collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
-
-            // Negative 0 - apparently there's a difference in floating point arithmetic - FML
-            assertThat(translationY).isEqualTo(-0f)
-            val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
-            assertThat(translationY).isEqualTo(expected1)
-            val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
-            assertThat(translationY).isEqualTo(expected2)
-            val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
-            assertThat(translationY).isEqualTo(expected3)
-            val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
-            assertThat(translationY).isEqualTo(expected4)
-        }
-
-    @Test
     fun visibilityWhenCommunalNotShowing() =
         testScope.runTest {
             keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
@@ -185,13 +137,5 @@
     companion object {
         private const val DEFAULT_BURN_IN_OFFSET = 5
         private const val RETURNED_BURN_IN_OFFSET = 3
-
-        @JvmStatic
-        @Parameters(name = "{0}")
-        fun getParams(): List<FlagsParameterization> {
-            return FlagsParameterization.allCombinationsOf(
-                FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
-            )
-        }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index 95ffc96..789477e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -19,12 +19,10 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
-import android.platform.test.annotations.EnableFlags
 import android.platform.test.flag.junit.FlagsParameterization
 import android.view.View
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.communal.data.repository.communalSceneRepository
 import com.android.systemui.communal.shared.model.CommunalScenes
@@ -73,7 +71,6 @@
 
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4::class)
-@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
 class KeyguardRootViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index 6f7e9d3..e4eb55b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -26,9 +26,7 @@
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.DisableSceneContainer
-import com.android.systemui.flags.Flags
 import com.android.systemui.flags.andSceneContainer
-import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
 import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
 import com.android.systemui.keyguard.shared.model.ClockSize
@@ -77,7 +75,6 @@
     @Before
     fun setup() {
         with(kosmos) {
-            fakeFeatureFlagsClassic.set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, true)
             shadeRepository.setShadeLayoutWide(false)
             underTest = lockscreenContentViewModel
             underTest.activateIn(testScope)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
index fba3997..d909c5a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelTest.kt
@@ -32,7 +32,7 @@
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.data.repository.sceneContainerRepository
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -161,8 +161,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
                 checkInterpolatedValues = false,
@@ -178,8 +178,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.minBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
             )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
index b406e6c..6895794 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelTest.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -141,17 +141,16 @@
         }
 
     @Test
-    fun blurRadiusGoesToMinImmediately() =
+    fun blurRadiusGoesFromMaxToMin() =
         testScope.runTest {
             val values by collectValues(underTest.windowBlurRadius)
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.minBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
-                checkInterpolatedValues = false,
             )
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt
index a8f0f2f..4013c70 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelTest.kt
@@ -30,7 +30,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -130,11 +130,10 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.minBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
-                checkInterpolatedValues = false,
             )
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
index 2c6e553..f3f4c89 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelTest.kt
@@ -23,7 +23,7 @@
 import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -47,8 +47,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.minBlurRadiusPx,
+                endValue = kosmos.blurConfig.minBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = { step, transitionState ->
                     TransitionStep(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
index 9e5976f..bae49fa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelTest.kt
@@ -27,7 +27,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.testKosmos
 import com.google.common.collect.Range
@@ -120,8 +120,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.minBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
             )
@@ -135,8 +135,8 @@
 
             kosmos.bouncerWindowBlurTestUtil.assertTransitionToBlurRadius(
                 transitionProgress = listOf(0.0f, 0.2f, 0.3f, 0.65f, 0.7f, 1.0f),
-                startValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
-                endValue = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS,
+                startValue = kosmos.blurConfig.maxBlurRadiusPx,
+                endValue = kosmos.blurConfig.maxBlurRadiusPx,
                 actualValuesProvider = { values },
                 transitionFactory = ::step,
                 checkInterpolatedValues = false,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
index 2f95936..3be9e18 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaControllerTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.media.controls.ui.controller
 
-import android.provider.Settings
 import android.testing.TestableLooper
 import android.view.View.GONE
 import android.view.View.VISIBLE
@@ -88,7 +87,7 @@
                 configurationController,
                 ResourcesSplitShadeStateController(),
                 mock<KeyguardMediaControllerLogger>(),
-                mock<DumpManager>()
+                mock<DumpManager>(),
             )
         keyguardMediaController.attachSinglePaneContainer(mediaContainerView)
         keyguardMediaController.useSplitShade = false
@@ -142,7 +141,7 @@
 
         assertTrue(
             "HostView wasn't attached to the split pane container",
-            splitShadeContainer.childCount == 1
+            splitShadeContainer.childCount == 1,
         )
     }
 
@@ -153,7 +152,7 @@
 
         assertTrue(
             "HostView wasn't attached to the single pane container",
-            mediaContainerView.childCount == 1
+            mediaContainerView.childCount == 1,
         )
     }
 
@@ -174,17 +173,6 @@
     }
 
     @Test
-    fun dozeWakeUpAnimationWaiting_inSplitShade_mediaIsHidden() {
-        val splitShadeContainer = FrameLayout(context)
-        keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
-        keyguardMediaController.useSplitShade = true
-
-        keyguardMediaController.isDozeWakeUpAnimationWaiting = true
-
-        assertThat(splitShadeContainer.visibility).isEqualTo(GONE)
-    }
-
-    @Test
     fun dozing_inSingleShade_mediaIsVisible() {
         val splitShadeContainer = FrameLayout(context)
         keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
@@ -195,17 +183,6 @@
         assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
     }
 
-    @Test
-    fun dozeWakeUpAnimationWaiting_inSingleShade_mediaIsVisible() {
-        val splitShadeContainer = FrameLayout(context)
-        keyguardMediaController.attachSplitShadeContainer(splitShadeContainer)
-        keyguardMediaController.useSplitShade = false
-
-        keyguardMediaController.isDozeWakeUpAnimationWaiting = true
-
-        assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE)
-    }
-
     private fun setDozing() {
         whenever(statusBarStateController.isDozing).thenReturn(true)
         statusBarStateListener.onDozingChanged(true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt
index 77be8c7..6ec38ba 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepositoryTest.kt
@@ -16,8 +16,9 @@
 
 package com.android.systemui.mediarouter.data.repository
 
-import androidx.test.filters.SmallTest
+import android.media.projection.StopReason
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.kosmos.Kosmos
@@ -101,7 +102,7 @@
                 origin = CastDevice.CastOrigin.MediaRouter,
             )
 
-        underTest.stopCasting(device)
+        underTest.stopCasting(device, StopReason.STOP_UNKNOWN)
 
         assertThat(castController.lastStoppedDevice).isEqualTo(device)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
index 004aeb0..3d9fb0a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/FgsManagerControllerTest.java
@@ -56,6 +56,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.util.DeviceConfigProxyFake;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -84,6 +85,7 @@
     FakeExecutor mMainExecutor;
     FakeExecutor mBackgroundExecutor;
     DeviceConfigProxyFake mDeviceConfigProxyFake;
+    FakeShadeDialogContextInteractor mFakeShadeDialogContextInteractor;
 
     @Mock
     IActivityManager mIActivityManager;
@@ -118,6 +120,7 @@
     public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
 
+        mFakeShadeDialogContextInteractor = new FakeShadeDialogContextInteractor(mContext);
         mDeviceConfigProxyFake = new DeviceConfigProxyFake();
         mSystemClock = new FakeSystemClock();
         mMainExecutor = new FakeExecutor(mSystemClock);
@@ -346,7 +349,6 @@
                 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
                 "true", false);
         FgsManagerController fmc = new FgsManagerControllerImpl(
-                mContext,
                 mContext.getResources(),
                 mMainExecutor,
                 mBackgroundExecutor,
@@ -359,7 +361,8 @@
                 mDialogTransitionAnimator,
                 mBroadcastDispatcher,
                 mDumpManager,
-                mSystemUIDialogFactory
+                mSystemUIDialogFactory,
+                mFakeShadeDialogContextInteractor
         );
         fmc.init();
         Assert.assertTrue(fmc.getIncludesUserVisibleJobs());
@@ -374,7 +377,6 @@
                 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS,
                 "false", false);
         fmc = new FgsManagerControllerImpl(
-                mContext,
                 mContext.getResources(),
                 mMainExecutor,
                 mBackgroundExecutor,
@@ -387,7 +389,8 @@
                 mDialogTransitionAnimator,
                 mBroadcastDispatcher,
                 mDumpManager,
-                mSystemUIDialogFactory
+                mSystemUIDialogFactory,
+                mFakeShadeDialogContextInteractor
         );
         fmc.init();
         Assert.assertFalse(fmc.getIncludesUserVisibleJobs());
@@ -487,7 +490,6 @@
                 ArgumentCaptor.forClass(BroadcastReceiver.class);
 
         FgsManagerController result = new FgsManagerControllerImpl(
-                mContext,
                 mContext.getResources(),
                 mMainExecutor,
                 mBackgroundExecutor,
@@ -500,7 +502,8 @@
                 mDialogTransitionAnimator,
                 mBroadcastDispatcher,
                 mDumpManager,
-                mSystemUIDialogFactory
+                mSystemUIDialogFactory,
+                mFakeShadeDialogContextInteractor
         );
         result.init();
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/TileServiceRequestControllerTestComposeOn.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/TileServiceRequestControllerTestComposeOn.kt
index f02856c..f48027b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/TileServiceRequestControllerTestComposeOn.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/TileServiceRequestControllerTestComposeOn.kt
@@ -148,7 +148,7 @@
     @Test
     fun showAllUsers_set() =
         kosmos.runTest {
-            val dialog = runOnMainThreadAndWaitForIdleSync {
+            val dialog = createDialog {
                 underTest.requestTileAdd(
                     TEST_UID,
                     TEST_COMPONENT,
@@ -158,7 +158,6 @@
                     Callback(),
                 )!!
             }
-            onTeardown { dialog.cancel() }
 
             assertThat(dialog.isShowForAllUsers).isTrue()
         }
@@ -166,7 +165,7 @@
     @Test
     fun cancelOnTouchOutside_set() =
         kosmos.runTest {
-            val dialog = runOnMainThreadAndWaitForIdleSync {
+            val dialog = createDialog {
                 underTest.requestTileAdd(
                     TEST_UID,
                     TEST_COMPONENT,
@@ -176,11 +175,16 @@
                     Callback(),
                 )!!
             }
-            onTeardown { dialog.cancel() }
 
             assertThat(dialog.isCancelOnTouchOutside).isTrue()
         }
 
+    fun <T : DialogInterface> createDialog(constructor: () -> T): T {
+        val dialog = runOnMainThreadAndWaitForIdleSync { constructor() }
+        onTeardown { runOnMainThreadAndWaitForIdleSync { dialog.cancel() } }
+        return dialog
+    }
+
     @Test
     fun positiveAction_tileAdded() =
         kosmos.runTest {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/ui/viewmodel/TileRequestDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/ui/viewmodel/TileRequestDialogViewModelTest.kt
index 369975a..3029928 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/ui/viewmodel/TileRequestDialogViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/external/ui/viewmodel/TileRequestDialogViewModelTest.kt
@@ -89,7 +89,7 @@
                 expect.that(state).isEqualTo(expectedState.state)
                 expect.that(handlesLongClick).isFalse()
                 expect.that(handlesSecondaryClick).isFalse()
-                expect.that(icon.get()).isEqualTo(defaultIcon)
+                expect.that(icon).isEqualTo(defaultIcon)
                 expect.that(sideDrawable).isNull()
                 expect.that(accessibilityUiState).isEqualTo(expectedState.accessibilityUiState)
             }
@@ -112,7 +112,7 @@
                 expect.that(state).isEqualTo(expectedState.state)
                 expect.that(handlesLongClick).isFalse()
                 expect.that(handlesSecondaryClick).isFalse()
-                expect.that(icon.get()).isEqualTo(QSTileImpl.DrawableIcon(loadedDrawable))
+                expect.that(icon).isEqualTo(QSTileImpl.DrawableIcon(loadedDrawable))
                 expect.that(sideDrawable).isNull()
                 expect.that(accessibilityUiState).isEqualTo(expectedState.accessibilityUiState)
             }
@@ -135,7 +135,7 @@
             underTest.activateIn(testScope)
             runCurrent()
 
-            assertThat(underTest.uiState.icon.get()).isEqualTo(defaultIcon)
+            assertThat(underTest.uiState.icon).isEqualTo(defaultIcon)
         }
 
     companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/EditModeButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt
similarity index 100%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/toolbar/EditModeButtonViewModelTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiStateTest.kt
index b144f06..9c8e322 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiStateTest.kt
@@ -18,6 +18,7 @@
 
 import android.content.res.Resources
 import android.content.res.mainResources
+import android.graphics.drawable.TestStubDrawable
 import android.service.quicksettings.Tile
 import android.widget.Button
 import android.widget.Switch
@@ -26,9 +27,12 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.qs.tileimpl.QSTileImpl.ResourceIcon
 import com.android.systemui.res.R
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
+import java.util.function.Supplier
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -263,6 +267,45 @@
             .contains(resources.getString(R.string.tile_unavailable))
     }
 
+    @Test
+    fun iconAndSupplier_prefersIcon() {
+        val state =
+            QSTile.State().apply {
+                icon = ResourceIcon.get(R.drawable.android)
+                iconSupplier = Supplier { QSTileImpl.DrawableIcon(TestStubDrawable()) }
+            }
+        val uiState = state.toUiState()
+
+        assertThat(uiState.icon).isEqualTo(state.icon)
+    }
+
+    @Test
+    fun iconOnly_hasIcon() {
+        val state = QSTile.State().apply { icon = ResourceIcon.get(R.drawable.android) }
+        val uiState = state.toUiState()
+
+        assertThat(uiState.icon).isEqualTo(state.icon)
+    }
+
+    @Test
+    fun supplierOnly_hasIcon() {
+        val state =
+            QSTile.State().apply {
+                iconSupplier = Supplier { ResourceIcon.get(R.drawable.android) }
+            }
+        val uiState = state.toUiState()
+
+        assertThat(uiState.icon).isEqualTo(state.iconSupplier.get())
+    }
+
+    @Test
+    fun noIconOrSupplier_iconNull() {
+        val state = QSTile.State()
+        val uiState = state.toUiState()
+
+        assertThat(uiState.icon).isNull()
+    }
+
     private fun QSTile.State.toUiState() = toUiState(resources)
 }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 9f12b18..31a627f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -20,6 +20,7 @@
 import static junit.framework.TestCase.assertEquals;
 
 import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
@@ -30,6 +31,7 @@
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
 import android.media.projection.MediaProjectionInfo;
+import android.media.projection.StopReason;
 import android.os.Handler;
 import android.service.quicksettings.Tile;
 import android.testing.TestableLooper;
@@ -336,7 +338,8 @@
         mCastTile.handleClick(null /* view */);
         mTestableLooper.processAllMessages();
 
-        verify(mController, times(1)).stopCasting(same(device));
+        verify(mController, times(1))
+                .stopCasting(same(device), eq(StopReason.STOP_QS_TILE));
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index fbbdc46..0e823cc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIconWithRes
 import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.policy.DataSaverController
 import com.android.systemui.util.mockito.whenever
@@ -96,6 +97,7 @@
                 dataSaverController,
                 mDialogTransitionAnimator,
                 systemUIDialogFactory,
+                FakeShadeDialogContextInteractor(mContext),
             )
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 0fd7c98..fc1d73b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -27,11 +27,13 @@
 import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Dialog;
+import android.media.projection.StopReason;
 import android.os.Handler;
 import android.platform.test.flag.junit.FlagsParameterization;
 import android.service.quicksettings.Tile;
@@ -234,7 +236,7 @@
 
         mTile.handleClick(null /* view */);
 
-        verify(mController, times(1)).stopRecording();
+        verify(mController, times(1)).stopRecording(eq(StopReason.STOP_QS_TILE));
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
index 056efb3..c47a412 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImplTest.kt
@@ -117,7 +117,6 @@
                     "test_spec:\n" +
                         "    QSTileState(" +
                         "icon=Resource(res=0, contentDescription=Resource(res=0)), " +
-                        "iconRes=null, " +
                         "label=test_data, " +
                         "activationState=INACTIVE, " +
                         "secondaryLabel=null, " +
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index b888617..5c6657b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -8,6 +8,7 @@
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -231,7 +232,8 @@
 
         mViewHolder.onWifiClick(mWifiEntry, mock(View.class));
 
-        verify(mSpyContext).startActivity(any());
+        verify(mInternetDialogController).startActivityForDialog(any());
+        verify(mSpyContext, never()).startActivity(any());
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/AirplaneModeMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/AirplaneModeMapperTest.kt
index 00460bf..557f4ea 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/AirplaneModeMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/AirplaneModeMapperTest.kt
@@ -93,8 +93,7 @@
     ): QSTileState {
         val label = context.getString(R.string.airplane_mode)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt
index 632aae0..24e4668 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapperTest.kt
@@ -178,8 +178,7 @@
     ): QSTileState {
         val label = context.getString(R.string.status_bar_alarm)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(R.drawable.ic_alarm)!!, null),
-            R.drawable.ic_alarm,
+            Icon.Loaded(context.getDrawable(R.drawable.ic_alarm)!!, null, R.drawable.ic_alarm),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapperTest.kt
index 5385f94..2ddaddd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapperTest.kt
@@ -253,8 +253,7 @@
     ): QSTileState {
         val label = context.getString(R.string.battery_detail_switch_title)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt
index 356b98e..a3c159820 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapperTest.kt
@@ -77,8 +77,11 @@
     ): QSTileState {
         val label = context.getString(R.string.quick_settings_color_correction_label)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(R.drawable.ic_qs_color_correction)!!, null),
-            R.drawable.ic_qs_color_correction,
+            Icon.Loaded(
+                context.getDrawable(R.drawable.ic_qs_color_correction)!!,
+                null,
+                R.drawable.ic_qs_color_correction,
+            ),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileMapperTest.kt
index 8236c4c..608adf1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileMapperTest.kt
@@ -253,7 +253,6 @@
     ): QSTileState {
         return QSTileState(
             icon?.let { com.android.systemui.common.shared.model.Icon.Loaded(icon, null) },
-            null,
             "test label",
             activationState,
             "test subtitle",
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapperTest.kt
index 587585c..a115c12 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapperTest.kt
@@ -73,7 +73,11 @@
             mapper.map(qsTileConfig, FlashlightTileModel.FlashlightAvailable(true))
 
         val expectedIcon =
-            Icon.Loaded(context.getDrawable(R.drawable.qs_flashlight_icon_on)!!, null)
+            Icon.Loaded(
+                context.getDrawable(R.drawable.qs_flashlight_icon_on)!!,
+                null,
+                R.drawable.qs_flashlight_icon_on,
+            )
         val actualIcon = tileState.icon
         assertThat(actualIcon).isEqualTo(expectedIcon)
     }
@@ -84,7 +88,11 @@
             mapper.map(qsTileConfig, FlashlightTileModel.FlashlightAvailable(false))
 
         val expectedIcon =
-            Icon.Loaded(context.getDrawable(R.drawable.qs_flashlight_icon_off)!!, null)
+            Icon.Loaded(
+                context.getDrawable(R.drawable.qs_flashlight_icon_off)!!,
+                null,
+                R.drawable.qs_flashlight_icon_off,
+            )
         val actualIcon = tileState.icon
         assertThat(actualIcon).isEqualTo(expectedIcon)
     }
@@ -95,7 +103,11 @@
             mapper.map(qsTileConfig, FlashlightTileModel.FlashlightTemporarilyUnavailable)
 
         val expectedIcon =
-            Icon.Loaded(context.getDrawable(R.drawable.qs_flashlight_icon_off)!!, null)
+            Icon.Loaded(
+                context.getDrawable(R.drawable.qs_flashlight_icon_off)!!,
+                null,
+                R.drawable.qs_flashlight_icon_off,
+            )
         val actualIcon = tileState.icon
         assertThat(actualIcon).isEqualTo(expectedIcon)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapperTest.kt
index e81771e..8f8f710 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapperTest.kt
@@ -58,8 +58,11 @@
 
     private fun createFontScalingTileState(): QSTileState =
         QSTileState(
-            Icon.Loaded(context.getDrawable(R.drawable.ic_qs_font_scaling)!!, null),
-            R.drawable.ic_qs_font_scaling,
+            Icon.Loaded(
+                context.getDrawable(R.drawable.ic_qs_font_scaling)!!,
+                null,
+                R.drawable.ic_qs_font_scaling,
+            ),
             context.getString(R.string.quick_settings_font_scaling_label),
             QSTileState.ActivationState.ACTIVE,
             null,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapperTest.kt
index 12d604f..3d3447d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapperTest.kt
@@ -102,8 +102,7 @@
         val label = context.getString(R.string.quick_settings_hearing_devices_label)
         val iconRes = R.drawable.qs_hearing_devices_icon
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapperTest.kt
index 9dcf49e..b087bbc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapperTest.kt
@@ -82,7 +82,6 @@
                 QSTileState.ActivationState.ACTIVE,
                 context.getString(R.string.quick_settings_networks_available),
                 Icon.Loaded(signalDrawable, null),
-                null,
                 context.getString(R.string.quick_settings_internet_label),
             )
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
@@ -120,8 +119,11 @@
             createInternetTileState(
                 QSTileState.ActivationState.ACTIVE,
                 inputModel.secondaryLabel.loadText(context).toString(),
-                Icon.Loaded(context.getDrawable(expectedSatIcon!!.res)!!, null),
-                expectedSatIcon.res,
+                Icon.Loaded(
+                    context.getDrawable(expectedSatIcon!!.res)!!,
+                    null,
+                    expectedSatIcon.res,
+                ),
                 expectedSatIcon.contentDescription.loadContentDescription(context).toString(),
             )
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
@@ -144,8 +146,7 @@
             createInternetTileState(
                 QSTileState.ActivationState.ACTIVE,
                 context.getString(R.string.quick_settings_networks_available),
-                Icon.Loaded(context.getDrawable(wifiRes)!!, contentDescription = null),
-                wifiRes,
+                Icon.Loaded(context.getDrawable(wifiRes)!!, null, wifiRes),
                 context.getString(R.string.quick_settings_internet_label),
             )
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
@@ -171,8 +172,8 @@
                 Icon.Loaded(
                     context.getDrawable(R.drawable.ic_qs_no_internet_unavailable)!!,
                     contentDescription = null,
+                    R.drawable.ic_qs_no_internet_unavailable,
                 ),
-                R.drawable.ic_qs_no_internet_unavailable,
                 context.getString(R.string.quick_settings_networks_unavailable),
             )
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
@@ -182,13 +183,11 @@
         activationState: QSTileState.ActivationState,
         secondaryLabel: String,
         icon: Icon,
-        iconRes: Int? = null,
         contentDescription: String,
     ): QSTileState {
         val label = context.getString(R.string.quick_settings_internet_label)
         return QSTileState(
             icon,
-            iconRes,
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt
index 30fce73..780d58c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapperTest.kt
@@ -90,8 +90,7 @@
     ): QSTileState {
         val label = context.getString(R.string.quick_settings_inversion_label)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapperTest.kt
index 37e8a60..4ebe23dc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapperTest.kt
@@ -69,7 +69,12 @@
     fun mapsEnabledDataToOnIconState() {
         val tileState: QSTileState = mapper.map(qsTileConfig, LocationTileModel(true))
 
-        val expectedIcon = Icon.Loaded(context.getDrawable(R.drawable.qs_location_icon_on)!!, null)
+        val expectedIcon =
+            Icon.Loaded(
+                context.getDrawable(R.drawable.qs_location_icon_on)!!,
+                null,
+                R.drawable.qs_location_icon_on,
+            )
         val actualIcon = tileState.icon
         Truth.assertThat(actualIcon).isEqualTo(expectedIcon)
     }
@@ -78,7 +83,12 @@
     fun mapsDisabledDataToOffIconState() {
         val tileState: QSTileState = mapper.map(qsTileConfig, LocationTileModel(false))
 
-        val expectedIcon = Icon.Loaded(context.getDrawable(R.drawable.qs_location_icon_off)!!, null)
+        val expectedIcon =
+            Icon.Loaded(
+                context.getDrawable(R.drawable.qs_location_icon_off)!!,
+                null,
+                R.drawable.qs_location_icon_off,
+            )
         val actualIcon = tileState.icon
         Truth.assertThat(actualIcon).isEqualTo(expectedIcon)
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
index de3dc57..44e6b4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractorTest.kt
@@ -28,6 +28,7 @@
 import com.android.settingslib.notification.modes.TestModeBuilder
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.SysuiTestableContext
+import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.shared.model.asIcon
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
@@ -63,7 +64,7 @@
     fun setUp() {
         context.orCreateTestableResources.apply {
             addOverride(MODES_DRAWABLE_ID, MODES_DRAWABLE)
-            addOverride(R.drawable.ic_zen_mode_type_bedtime, BEDTIME_DRAWABLE)
+            addOverride(BEDTIME_DRAWABLE_ID, BEDTIME_DRAWABLE)
         }
 
         val customPackageContext = SysuiTestableContext(context)
@@ -145,24 +146,24 @@
             // Tile starts with the generic Modes icon.
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
 
             // Add an inactive mode -> Still modes icon
             zenModeRepository.addMode(id = "Mode", active = false)
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
 
             // Add an active mode with a default icon: icon should be the mode icon, and the
             // iconResId is also populated, because we know it's a system icon.
             zenModeRepository.addMode(
                 id = "Bedtime with default icon",
                 type = AutomaticZenRule.TYPE_BEDTIME,
-                active = true
+                active = true,
             )
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
+            assertThat(tileData?.icon!!.res).isEqualTo(BEDTIME_DRAWABLE_ID)
 
             // Add another, less-prioritized mode that has a *custom* icon: for now, icon should
             // remain the first mode icon
@@ -177,20 +178,20 @@
             )
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(BEDTIME_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(R.drawable.ic_zen_mode_type_bedtime)
+            assertThat(tileData?.icon!!.res).isEqualTo(BEDTIME_DRAWABLE_ID)
 
             // Deactivate more important mode: icon should be the less important, still active mode
             // And because it's a package-provided icon, iconResId is not populated.
             zenModeRepository.deactivateMode("Bedtime with default icon")
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(CUSTOM_ICON)
-            assertThat(tileData?.iconResId).isNull()
+            assertThat(tileData?.icon!!.res).isNull()
 
             // Deactivate remaining mode: back to the default modes icon
             zenModeRepository.deactivateMode("Driving with custom icon")
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
         }
 
     @Test
@@ -205,18 +206,18 @@
 
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
 
             // Activate a Mode -> Icon doesn't change.
             zenModeRepository.addMode(id = "Mode", active = true)
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
 
             zenModeRepository.deactivateMode(id = "Mode")
             runCurrent()
             assertThat(tileData?.icon).isEqualTo(MODES_ICON)
-            assertThat(tileData?.iconResId).isEqualTo(MODES_DRAWABLE_ID)
+            assertThat(tileData?.icon!!.res).isEqualTo(MODES_DRAWABLE_ID)
         }
 
     @EnableFlags(Flags.FLAG_MODES_UI)
@@ -256,15 +257,17 @@
         val TEST_USER = UserHandle.of(1)!!
         const val CUSTOM_PACKAGE = "com.some.mode.owner.package"
 
-        val MODES_DRAWABLE_ID = R.drawable.ic_zen_priority_modes
+        const val MODES_DRAWABLE_ID = R.drawable.ic_zen_priority_modes
         const val CUSTOM_DRAWABLE_ID = 12345
 
+        const val BEDTIME_DRAWABLE_ID = R.drawable.ic_zen_mode_type_bedtime
+
         val MODES_DRAWABLE = TestStubDrawable("modes_icon")
         val BEDTIME_DRAWABLE = TestStubDrawable("bedtime")
         val CUSTOM_DRAWABLE = TestStubDrawable("custom")
 
-        val MODES_ICON = MODES_DRAWABLE.asIcon()
-        val BEDTIME_ICON = BEDTIME_DRAWABLE.asIcon()
+        val MODES_ICON = Icon.Loaded(MODES_DRAWABLE, null, MODES_DRAWABLE_ID)
+        val BEDTIME_ICON = Icon.Loaded(BEDTIME_DRAWABLE, null, BEDTIME_DRAWABLE_ID)
         val CUSTOM_ICON = CUSTOM_DRAWABLE.asIcon()
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt
index 88b0046..04e094f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileUserActionInteractorTest.kt
@@ -156,6 +156,10 @@
     }
 
     private fun modelOf(isActivated: Boolean, activeModeNames: List<String>): ModesTileModel {
-        return ModesTileModel(isActivated, activeModeNames, TestStubDrawable("icon").asIcon(), 123)
+        return ModesTileModel(
+            isActivated,
+            activeModeNames,
+            TestStubDrawable("icon").asIcon(res = 123),
+        )
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
index 4e91d16..d73044f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapperTest.kt
@@ -99,18 +99,11 @@
 
     @Test
     fun state_modelHasIconResId_includesIconResId() {
-        val icon = TestStubDrawable("res123").asIcon()
-        val model =
-            ModesTileModel(
-                isActivated = false,
-                activeModes = emptyList(),
-                icon = icon,
-                iconResId = 123,
-            )
+        val icon = TestStubDrawable("res123").asIcon(res = 123)
+        val model = ModesTileModel(isActivated = false, activeModes = emptyList(), icon = icon)
 
         val state = underTest.map(config, model)
 
         assertThat(state.icon).isEqualTo(icon)
-        assertThat(state.iconRes).isEqualTo(123)
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapperTest.kt
index 1457f53..7c85326 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapperTest.kt
@@ -289,8 +289,7 @@
             if (TextUtils.isEmpty(secondaryLabel)) label
             else TextUtils.concat(label, ", ", secondaryLabel)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapperTest.kt
index 2ac3e08..b6caa22 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapperTest.kt
@@ -58,8 +58,11 @@
 
     private fun createNotesTileState(): QSTileState =
         QSTileState(
-            Icon.Loaded(context.getDrawable(R.drawable.ic_qs_notes)!!, null),
-            R.drawable.ic_qs_notes,
+            Icon.Loaded(
+                context.getDrawable(R.drawable.ic_qs_notes)!!,
+                null,
+                R.drawable.ic_qs_notes,
+            ),
             context.getString(R.string.quick_settings_notes_label),
             QSTileState.ActivationState.INACTIVE,
             /* secondaryLabel= */ null,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt
index 7782d2b..5b39810 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapperTest.kt
@@ -66,11 +66,7 @@
         val outputState = mapper.map(config, inputModel)
 
         val expectedState =
-            createOneHandedModeTileState(
-                QSTileState.ActivationState.INACTIVE,
-                subtitleArray[1],
-                com.android.internal.R.drawable.ic_qs_one_handed_mode,
-            )
+            createOneHandedModeTileState(QSTileState.ActivationState.INACTIVE, subtitleArray[1])
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
     }
 
@@ -81,23 +77,21 @@
         val outputState = mapper.map(config, inputModel)
 
         val expectedState =
-            createOneHandedModeTileState(
-                QSTileState.ActivationState.ACTIVE,
-                subtitleArray[2],
-                com.android.internal.R.drawable.ic_qs_one_handed_mode,
-            )
+            createOneHandedModeTileState(QSTileState.ActivationState.ACTIVE, subtitleArray[2])
         QSTileStateSubject.assertThat(outputState).isEqualTo(expectedState)
     }
 
     private fun createOneHandedModeTileState(
         activationState: QSTileState.ActivationState,
         secondaryLabel: String,
-        iconRes: Int,
     ): QSTileState {
         val label = context.getString(R.string.quick_settings_onehanded_label)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(
+                context.getDrawable(com.android.internal.R.drawable.ic_qs_one_handed_mode)!!,
+                null,
+                com.android.internal.R.drawable.ic_qs_one_handed_mode,
+            ),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapperTest.kt
index ed33250..c572ff6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapperTest.kt
@@ -93,8 +93,8 @@
             Icon.Loaded(
                 context.getDrawable(com.android.systemui.res.R.drawable.ic_qr_code_scanner)!!,
                 null,
+                com.android.systemui.res.R.drawable.ic_qr_code_scanner,
             ),
-            com.android.systemui.res.R.drawable.ic_qr_code_scanner,
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt
index 85111fd..00017f9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapperTest.kt
@@ -85,8 +85,7 @@
                 R.drawable.qs_extra_dim_icon_on
             else R.drawable.qs_extra_dim_icon_off
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             context.resources
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapperTest.kt
index 53671ba..7401014 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapperTest.kt
@@ -180,8 +180,7 @@
     ): QSTileState {
         val label = context.getString(R.string.quick_settings_rotation_unlocked_label)
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapperTest.kt
index 9a45065..1fb5048 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapperTest.kt
@@ -91,8 +91,7 @@
             else context.resources.getStringArray(R.array.tile_states_saver)[0]
 
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
index 0b56d7b..778c73f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractorTest.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
 
 import android.app.Dialog
+import android.media.projection.StopReason
 import android.os.UserHandle
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -92,7 +93,7 @@
 
         underTest.handleInput(QSTileInputTestKtx.click(recordingModel))
 
-        verify(recordingController).stopRecording()
+        verify(recordingController).stopRecording(eq(StopReason.STOP_QS_TILE))
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt
index cd683c4..3632556 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/screenrecord/ui/ScreenRecordTileMapperTest.kt
@@ -110,8 +110,7 @@
         val label = context.getString(R.string.quick_settings_screen_record_label)
 
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapperTest.kt
index c569403..e4cd0e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapperTest.kt
@@ -146,8 +146,7 @@
             else context.getString(R.string.quick_settings_mic_label)
 
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapperTest.kt
index 0d2ebe4..8f5f2d3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapperTest.kt
@@ -69,8 +69,7 @@
         expandedAccessibilityClass: KClass<out View>? = Switch::class,
     ): QSTileState {
         return QSTileState(
-            Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes,
+            Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label,
             activationState,
             secondaryLabel,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapperTest.kt
index 86321ea..2c81f39 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapperTest.kt
@@ -109,8 +109,7 @@
         val label = testLabel
         val iconRes = com.android.internal.R.drawable.stat_sys_managed_profile_status
         return QSTileState(
-            icon = Icon.Loaded(context.getDrawable(iconRes)!!, null),
-            iconRes = iconRes,
+            icon = Icon.Loaded(context.getDrawable(iconRes)!!, null, iconRes),
             label = label,
             activationState = activationState,
             secondaryLabel =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
index 039a1dc..518a0a5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.qs.PseudoGridView
 import com.android.systemui.qs.QSUserSwitcherEvent
 import com.android.systemui.qs.tiles.UserDetailView
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
@@ -84,6 +85,7 @@
                 mDialogTransitionAnimator,
                 uiEventLogger,
                 dialogFactory,
+                FakeShadeDialogContextInteractor(mContext),
             )
     }
 
@@ -91,32 +93,32 @@
     fun showDialog_callsDialogShow() {
         val launchController = mock<DialogTransitionAnimator.Controller>()
         `when`(launchExpandable.dialogTransitionController(any())).thenReturn(launchController)
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
         verify(mDialogTransitionAnimator).show(eq(dialog), eq(launchController), anyBoolean())
         verify(uiEventLogger).log(QSUserSwitcherEvent.QS_USER_DETAIL_OPEN)
     }
 
     @Test
     fun dialog_showForAllUsers() {
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
         verify(dialog).setShowForAllUsers(true)
     }
 
     @Test
     fun dialog_cancelOnTouchOutside() {
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
         verify(dialog).setCanceledOnTouchOutside(true)
     }
 
     @Test
     fun adapterAndGridLinked() {
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
         verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>())
     }
 
     @Test
     fun doneButtonLogsCorrectly() {
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
 
         verify(dialog).setPositiveButton(anyInt(), capture(clickCaptor))
 
@@ -129,7 +131,7 @@
     fun clickSettingsButton_noFalsing_opensSettings() {
         `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false)
 
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
 
         verify(dialog)
             .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */)
@@ -150,7 +152,7 @@
     fun clickSettingsButton_Falsing_notOpensSettings() {
         `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true)
 
-        controller.showDialog(context, launchExpandable)
+        controller.showDialog(launchExpandable)
 
         verify(dialog)
             .setNeutralButton(anyInt(), capture(clickCaptor), eq(false) /* dismissOnClick */)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index e56b965..3187cca6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -37,7 +37,6 @@
 import com.android.systemui.bouncer.ui.viewmodel.PasswordBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.bouncerSceneContentViewModel
-import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.EnableSceneContainer
@@ -48,9 +47,9 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.collectLastValue
 import com.android.systemui.kosmos.currentValue
-import com.android.systemui.kosmos.runCurrent
 import com.android.systemui.kosmos.runTest
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.verifyCurrent
 import com.android.systemui.lifecycle.activateIn
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
@@ -77,12 +76,9 @@
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.advanceTimeBy
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mockito.verify
 
 /**
  * Integration test cases for the Scene Framework.
@@ -137,10 +133,10 @@
             sceneContainerViewModel.activateIn(testScope)
 
             assertWithMessage("Initial scene key mismatch!")
-                .that(sceneContainerViewModel.currentScene.value)
+                .that(currentValue(sceneContainerViewModel.currentScene))
                 .isEqualTo(sceneContainerConfig.initialSceneKey)
             assertWithMessage("Initial scene container visibility mismatch!")
-                .that(sceneContainerViewModel.isVisible)
+                .that(currentValue { sceneContainerViewModel.isVisible })
                 .isTrue()
         }
 
@@ -337,7 +333,6 @@
                 .that(bouncerActionButton)
                 .isNotNull()
             kosmos.bouncerSceneContentViewModel.onActionButtonClicked(bouncerActionButton!!)
-            runCurrent()
 
             // TODO(b/369765704): Assert that an activity was started once we use ActivityStarter.
         }
@@ -358,9 +353,8 @@
                 .that(bouncerActionButton)
                 .isNotNull()
             kosmos.bouncerSceneContentViewModel.onActionButtonClicked(bouncerActionButton!!)
-            runCurrent()
 
-            verify(mockTelecomManager).showInCallScreen(any())
+            verifyCurrent(mockTelecomManager).showInCallScreen(any())
         }
 
     @Test
@@ -413,7 +407,7 @@
      * the UI must gradually transition between scenes.
      */
     private fun Kosmos.getCurrentSceneInUi(): SceneKey {
-        return when (val state = transitionState.value) {
+        return when (val state = currentValue(transitionState)) {
             is ObservableTransitionState.Idle -> state.currentScene
             is ObservableTransitionState.Transition.ChangeScene -> state.fromScene
             is ObservableTransitionState.Transition.ShowOrHideOverlay -> state.currentScene
@@ -436,7 +430,6 @@
         // is not an observable that can trigger a new evaluation.
         fakeDeviceEntryRepository.setLockscreenEnabled(enableLockscreen)
         fakeAuthenticationRepository.setAuthenticationMethod(authMethod)
-        testScope.runCurrent()
     }
 
     /** Emulates a phone call in progress. */
@@ -447,7 +440,6 @@
             setIsInCall(true)
             setCallState(TelephonyManager.CALL_STATE_OFFHOOK)
         }
-        testScope.runCurrent()
     }
 
     /**
@@ -480,24 +472,21 @@
                 isInitiatedByUserInput = false,
                 isUserInputOngoing = flowOf(false),
             )
-        testScope.runCurrent()
 
         // Report progress of transition.
-        while (progressFlow.value < 1f) {
+        while (currentValue(progressFlow) < 1f) {
             progressFlow.value += 0.2f
-            testScope.runCurrent()
         }
 
         // End the transition and report the change.
         transitionState.value = ObservableTransitionState.Idle(to)
 
         fakeSceneDataSource.unpause(force = true)
-        testScope.runCurrent()
 
         assertWithMessage("Visibility mismatch after scene transition from $from to $to!")
-            .that(sceneContainerViewModel.isVisible)
+            .that(currentValue { sceneContainerViewModel.isVisible })
             .isEqualTo(expectedVisible)
-        assertThat(sceneContainerViewModel.currentScene.value).isEqualTo(to)
+        assertThat(currentValue(sceneContainerViewModel.currentScene)).isEqualTo(to)
 
         bouncerSceneJob =
             if (to == Scenes.Bouncer) {
@@ -510,7 +499,6 @@
                 bouncerSceneJob?.cancel()
                 null
             }
-        testScope.runCurrent()
     }
 
     /**
@@ -556,13 +544,12 @@
         )
 
         powerInteractor.setAwakeForTest()
-        testScope.runCurrent()
     }
 
     /** Unlocks the device by entering the correct PIN. Ends up in the Gone scene. */
     private fun Kosmos.unlockDevice() {
         assertWithMessage("Cannot unlock a device that's already unlocked!")
-            .that(deviceEntryInteractor.isUnlocked.value)
+            .that(currentValue(deviceEntryInteractor.isUnlocked))
             .isFalse()
 
         emulateUserDrivenTransition(Scenes.Bouncer)
@@ -595,7 +582,6 @@
             pinBouncerViewModel.onPinButtonClicked(digit)
         }
         pinBouncerViewModel.onAuthenticateButtonClicked()
-        testScope.runCurrent()
     }
 
     /**
@@ -625,26 +611,23 @@
         }
         pinBouncerViewModel.onAuthenticateButtonClicked()
         fakeMobileConnectionsRepository.isAnySimSecure.value = false
-        testScope.runCurrent()
 
         setAuthMethod(authMethodAfterSimUnlock, enableLockscreen)
-        testScope.runCurrent()
     }
 
     /** Changes device wakefulness state from asleep to awake, going through intermediary states. */
     private fun Kosmos.wakeUpDevice() {
-        val wakefulnessModel = powerInteractor.detailedWakefulness.value
+        val wakefulnessModel = currentValue(powerInteractor.detailedWakefulness)
         assertWithMessage("Cannot wake up device as it's already awake!")
             .that(wakefulnessModel.isAwake())
             .isFalse()
 
         powerInteractor.setAwakeForTest()
-        testScope.runCurrent()
     }
 
     /** Changes device wakefulness state from awake to asleep, going through intermediary states. */
     private suspend fun Kosmos.putDeviceToSleep(waitForLock: Boolean = true) {
-        val wakefulnessModel = powerInteractor.detailedWakefulness.value
+        val wakefulnessModel = currentValue(powerInteractor.detailedWakefulness)
         assertWithMessage("Cannot put device to sleep as it's already asleep!")
             .that(wakefulnessModel.isAwake())
             .isTrue()
@@ -659,22 +642,18 @@
                     )
                     .toLong()
             )
-        } else {
-            testScope.runCurrent()
         }
     }
 
     /** Emulates the dismissal of the IME (soft keyboard). */
     private fun Kosmos.dismissIme() {
-        (bouncerSceneContentViewModel.authMethodViewModel.value as? PasswordBouncerViewModel)?.let {
-            it.onImeDismissed()
-            testScope.runCurrent()
-        }
+        (currentValue(bouncerSceneContentViewModel.authMethodViewModel)
+                as? PasswordBouncerViewModel)
+            ?.let { it.onImeDismissed() }
     }
 
     private fun Kosmos.introduceLockedSim() {
         setAuthMethod(AuthenticationMethodModel.Sim)
         fakeMobileConnectionsRepository.isAnySimSecure.value = true
-        testScope.runCurrent()
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
index a6a1d4a..50fa9d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
@@ -41,6 +41,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.Intent;
+import android.media.projection.StopReason;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -199,16 +200,16 @@
     public void testOnSystemRequestedStop_recordingInProgress_endsRecording() throws IOException {
         doReturn(true).when(mController).isRecording();
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
-        verify(mScreenMediaRecorder).end();
+        verify(mScreenMediaRecorder).end(eq(StopReason.STOP_UNKNOWN));
     }
 
     @Test
     public void testOnSystemRequestedStop_recordingInProgress_updatesState() {
         doReturn(true).when(mController).isRecording();
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
         assertUpdateState(false);
     }
@@ -218,18 +219,18 @@
             throws IOException {
         doReturn(false).when(mController).isRecording();
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
-        verify(mScreenMediaRecorder, never()).end();
+        verify(mScreenMediaRecorder, never()).end(StopReason.STOP_UNKNOWN);
     }
 
     @Test
     public void testOnSystemRequestedStop_recorderEndThrowsRuntimeException_releasesRecording()
             throws IOException {
         doReturn(true).when(mController).isRecording();
-        doThrow(new RuntimeException()).when(mScreenMediaRecorder).end();
+        doThrow(new RuntimeException()).when(mScreenMediaRecorder).end(StopReason.STOP_UNKNOWN);
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
         verify(mScreenMediaRecorder).release();
     }
@@ -238,7 +239,7 @@
     public void testOnSystemRequestedStop_whenRecordingInProgress_showsNotifications() {
         doReturn(true).when(mController).isRecording();
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
         // Processing notification
         ArgumentCaptor<Notification> notifCaptor = ArgumentCaptor.forClass(Notification.class);
@@ -271,9 +272,9 @@
     public void testOnSystemRequestedStop_recorderEndThrowsRuntimeException_showsErrorNotification()
             throws IOException {
         doReturn(true).when(mController).isRecording();
-        doThrow(new RuntimeException()).when(mScreenMediaRecorder).end();
+        doThrow(new RuntimeException()).when(mScreenMediaRecorder).end(anyInt());
 
-        mRecordingService.onStopped();
+        mRecordingService.onStopped(StopReason.STOP_UNKNOWN);
 
         verify(mRecordingService).createErrorSavingNotification(any());
         ArgumentCaptor<Notification> notifCaptor = ArgumentCaptor.forClass(Notification.class);
@@ -289,9 +290,9 @@
     public void testOnSystemRequestedStop_recorderEndThrowsOOMError_releasesRecording()
             throws IOException {
         doReturn(true).when(mController).isRecording();
-        doThrow(new OutOfMemoryError()).when(mScreenMediaRecorder).end();
+        doThrow(new OutOfMemoryError()).when(mScreenMediaRecorder).end(anyInt());
 
-        assertThrows(Throwable.class, () -> mRecordingService.onStopped());
+        assertThrows(Throwable.class, () -> mRecordingService.onStopped(StopReason.STOP_UNKNOWN));
 
         verify(mScreenMediaRecorder).release();
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
index aceea90..ade5941 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepositoryTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenrecord.data.repository
 
+import android.media.projection.StopReason
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -31,6 +32,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
@@ -126,8 +128,8 @@
     @Test
     fun stopRecording_invokesController() =
         testScope.runTest {
-            underTest.stopRecording()
+            underTest.stopRecording(StopReason.STOP_PRIVACY_CHIP)
 
-            verify(recordingController).stopRecording()
+            verify(recordingController).stopRecording(eq(StopReason.STOP_PRIVACY_CHIP))
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index d3b5828..0e93167 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -28,15 +28,12 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -45,7 +42,6 @@
 import android.content.ContentResolver;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -56,8 +52,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityManager;
 
@@ -68,19 +62,11 @@
 import com.android.internal.logging.testing.UiEventLoggerFake;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardClockSwitchController;
 import com.android.keyguard.KeyguardSliceViewController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.keyguard.logging.KeyguardLogger;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
@@ -95,7 +81,6 @@
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.haptics.msdl.FakeMSDLPlayer;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.KeyguardViewConfigurator;
 import com.android.systemui.keyguard.data.repository.FakeKeyguardClockRepository;
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
@@ -103,14 +88,8 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
-import com.android.systemui.keyguard.ui.view.KeyguardRootView;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardTouchHandlingViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
 import com.android.systemui.media.controls.ui.controller.KeyguardMediaController;
@@ -147,12 +126,13 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.ConversationNotificationManager;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
 import com.android.systemui.statusbar.notification.data.repository.NotificationsKeyguardViewStateRepository;
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor;
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpTouchHelper;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -172,17 +152,13 @@
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.ShadeTouchableRegionManager;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.TapAgainViewController;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
 import com.android.systemui.statusbar.policy.SplitShadeStateController;
 import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository;
@@ -223,12 +199,9 @@
 
     @Mock protected CentralSurfaces mCentralSurfaces;
     @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
-    @Mock protected ViewPropertyAnimator mViewPropertyAnimator;
     @Mock protected HeadsUpManager mHeadsUpManager;
     @Mock protected NotificationGutsManager mGutsManager;
     @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
-    @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
-    @Mock protected ViewStub mUserSwitcherStubView;
     @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
     @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
     @Mock protected KeyguardBypassController mKeyguardBypassController;
@@ -249,36 +222,22 @@
     @Mock protected MetricsLogger mMetricsLogger;
     @Mock protected Resources mResources;
     @Mock protected Configuration mConfiguration;
-    @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
     @Mock protected MediaHierarchyManager mMediaHierarchyManager;
     @Mock protected ConversationNotificationManager mConversationNotificationManager;
     @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
-    @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
-    @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
-    @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
-    @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
-    @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
-    @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
-    @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
     @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
     @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
-    @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
     @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
     @Mock protected LightBarController mLightBarController;
     @Mock protected NotificationStackScrollLayoutController
             mNotificationStackScrollLayoutController;
     @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
     @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
-    @Mock protected AuthController mAuthController;
     @Mock protected ScrimController mScrimController;
     @Mock protected MediaDataManager mMediaDataManager;
     @Mock protected AmbientState mAmbientState;
     @Mock protected UserManager mUserManager;
     @Mock protected UiEventLogger mUiEventLogger;
-    @Mock protected KeyguardViewConfigurator mKeyguardViewConfigurator;
-    @Mock protected KeyguardRootView mKeyguardRootView;
-    @Mock protected View mKeyguardRootViewChild;
     @Mock protected KeyguardMediaController mKeyguardMediaController;
     @Mock protected NavigationModeController mNavigationModeController;
     @Mock protected NavigationBarController mNavigationBarController;
@@ -310,15 +269,6 @@
     @Mock protected ViewTreeObserver mViewTreeObserver;
     @Mock protected DreamingToLockscreenTransitionViewModel
             mDreamingToLockscreenTransitionViewModel;
-    @Mock protected OccludedToLockscreenTransitionViewModel
-            mOccludedToLockscreenTransitionViewModel;
-    @Mock protected LockscreenToDreamingTransitionViewModel
-            mLockscreenToDreamingTransitionViewModel;
-    @Mock protected LockscreenToOccludedTransitionViewModel
-            mLockscreenToOccludedTransitionViewModel;
-    @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-    @Mock protected PrimaryBouncerToGoneTransitionViewModel
-            mPrimaryBouncerToGoneTransitionViewModel;
     @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     @Mock protected KeyguardTouchHandlingViewModel mKeyuardTouchHandlingViewModel;
     @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
@@ -326,7 +276,6 @@
     @Mock protected CoroutineDispatcher mMainDispatcher;
     @Mock protected KeyguardSliceViewController mKeyguardSliceViewController;
     private final KeyguardLogger mKeyguardLogger = new KeyguardLogger(logcatLogBuffer());
-    @Mock protected KeyguardStatusView mKeyguardStatusView;
     @Captor
     protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
             mEmptySpaceClickListenerCaptor;
@@ -360,7 +309,6 @@
     protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
     protected Handler mMainHandler;
     protected View.OnLayoutChangeListener mLayoutChangeListener;
-    protected KeyguardStatusViewController mKeyguardStatusViewController;
     protected ShadeRepository mShadeRepository;
     protected FakeMSDLPlayer mMSDLPlayer = mKosmos.getMsdlPlayer();
 
@@ -442,23 +390,6 @@
                 () -> mKosmos.getSceneBackInteractor(),
                 () -> mKosmos.getAlternateBouncerInteractor());
 
-        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
-        keyguardStatusView.setId(R.id.keyguard_status_view);
-        mKeyguardStatusViewController = spy(new KeyguardStatusViewController(
-                mKeyguardStatusView,
-                mKeyguardSliceViewController,
-                mKeyguardClockSwitchController,
-                mKeyguardStateController,
-                mUpdateMonitor,
-                mConfigurationController,
-                mDozeParameters,
-                mScreenOffAnimationController,
-                mKeyguardLogger,
-                mKosmos.getInteractionJankMonitor(),
-                mKeyguardInteractor,
-                mPowerInteractor));
-
-        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
         when(mHeadsUpCallback.getContext()).thenReturn(mContext);
         when(mView.getResources()).thenReturn(mResources);
         when(mView.getWidth()).thenReturn(PANEL_WIDTH);
@@ -477,48 +408,21 @@
                 .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
         when(mView.getContext()).thenReturn(getContext());
         when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
-        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
-        when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
-                mUserSwitcherStubView);
-        when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
         when(mView.findViewById(R.id.notification_stack_scroller))
                 .thenReturn(mNotificationStackScrollLayout);
         when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
         when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
                 .thenReturn(mHeadsUpCallback);
-        when(mView.animate()).thenReturn(mViewPropertyAnimator);
-        when(mKeyguardStatusView.animate()).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.translationX(anyFloat())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.setStartDelay(anyLong())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.setInterpolator(any())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.setListener(any())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.setUpdateListener(any())).thenReturn(mViewPropertyAnimator);
-        when(mViewPropertyAnimator.withEndAction(any())).thenReturn(mViewPropertyAnimator);
-        when(mView.findViewById(R.id.keyguard_status_view))
-                .thenReturn(mock(KeyguardStatusView.class));
         ViewGroup rootView = mock(ViewGroup.class);
         when(rootView.isVisibleToUser()).thenReturn(true);
         when(mView.getRootView()).thenReturn(rootView);
-        when(rootView.findViewById(R.id.keyguard_status_view))
-                .thenReturn(mock(KeyguardStatusView.class));
         mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
-        mNotificationContainerParent.addView(keyguardStatusView);
         mNotificationContainerParent.onFinishInflate();
         when(mView.findViewById(R.id.notification_container_parent))
                 .thenReturn(mNotificationContainerParent);
         when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
         FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
                 mDisplayMetrics);
-        when(mKeyguardQsUserSwitchComponentFactory.build(any()))
-                .thenReturn(mKeyguardQsUserSwitchComponent);
-        when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
-                .thenReturn(mKeyguardQsUserSwitchController);
-        when(mKeyguardUserSwitcherComponentFactory.build(any()))
-                .thenReturn(mKeyguardUserSwitcherComponent);
-        when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
-                .thenReturn(mKeyguardUserSwitcherController);
         when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
         when(mQs.getView()).thenReturn(mView);
         when(mQSFragment.getView()).thenReturn(mView);
@@ -544,36 +448,6 @@
         when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
                 .thenReturn(emptyFlow());
 
-        // Occluded->Lockscreen
-        when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
-                .thenReturn(emptyFlow());
-        when(mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY())
-                .thenReturn(emptyFlow());
-
-        // Lockscreen->Dreaming
-        when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
-                .thenReturn(emptyFlow());
-        when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
-                .thenReturn(emptyFlow());
-
-        // Gone->Dreaming
-        when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
-                .thenReturn(emptyFlow());
-        when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
-                .thenReturn(emptyFlow());
-
-        // Lockscreen->Occluded
-        when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
-                .thenReturn(emptyFlow());
-        when(mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY())
-                .thenReturn(emptyFlow());
-
-        // Primary Bouncer->Gone
-        when(mPrimaryBouncerToGoneTransitionViewModel.getLockscreenAlpha())
-                .thenReturn(emptyFlow());
-        when(mPrimaryBouncerToGoneTransitionViewModel.getNotificationAlpha())
-                .thenReturn(emptyFlow());
-
         NotificationsKeyguardViewStateRepository notifsKeyguardViewStateRepository =
                 new NotificationsKeyguardViewStateRepository();
         NotificationsKeyguardInteractor notifsKeyguardInteractor =
@@ -615,20 +489,10 @@
                 mShadeInteractor,
                 mLockscreenShadeTransitionController,
                 mDumpManager);
-        when(mKeyguardStatusViewComponentFactory.build(any(), any()))
-                .thenReturn(mKeyguardStatusViewComponent);
-        when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
-                .thenReturn(mKeyguardClockSwitchController);
-        when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
-                .thenReturn(mKeyguardStatusViewController);
         when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
                 .thenReturn(mKeyguardStatusBarViewComponent);
         when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
                 .thenReturn(mKeyguardStatusBarViewController);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
-                .thenReturn(keyguardStatusView);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
-                .thenReturn(mUserSwitcherView);
         when(mNotificationRemoteInputManager.isRemoteInputActive())
                 .thenReturn(false);
         doAnswer(invocation -> {
@@ -665,9 +529,6 @@
         when(longPressHandlingView.getResources()).thenReturn(longPressHandlingViewRes);
         when(longPressHandlingViewRes.getString(anyInt())).thenReturn("");
 
-        when(mKeyguardRootView.findViewById(anyInt())).thenReturn(mKeyguardRootViewChild);
-        when(mKeyguardViewConfigurator.getKeyguardRootView()).thenReturn(mKeyguardRootView);
-
         mNotificationPanelViewController = new NotificationPanelViewController(
                 mView,
                 mMainHandler,
@@ -689,12 +550,8 @@
                 mGutsManager,
                 mNotificationsQSContainerController,
                 mNotificationStackScrollLayoutController,
-                mKeyguardStatusViewComponentFactory,
-                mKeyguardQsUserSwitchComponentFactory,
-                mKeyguardUserSwitcherComponentFactory,
                 mKeyguardStatusBarViewComponentFactory,
                 mLockscreenShadeTransitionController,
-                mAuthController,
                 mScrimController,
                 mUserManager,
                 mMediaDataManager,
@@ -724,11 +581,6 @@
                 mKeyguardClockInteractor,
                 mAlternateBouncerInteractor,
                 mDreamingToLockscreenTransitionViewModel,
-                mOccludedToLockscreenTransitionViewModel,
-                mLockscreenToDreamingTransitionViewModel,
-                mGoneToDreamingTransitionViewModel,
-                mLockscreenToOccludedTransitionViewModel,
-                mPrimaryBouncerToGoneTransitionViewModel,
                 mMainDispatcher,
                 mKeyguardTransitionInteractor,
                 mDumpManager,
@@ -738,7 +590,6 @@
                 mSharedNotificationContainerInteractor,
                 mActiveNotificationsInteractor,
                 mShadeAnimationInteractor,
-                mKeyguardViewConfigurator,
                 mDeviceEntryFaceAuthInteractor,
                 new ResourcesSplitShadeStateController(),
                 mPowerInteractor,
@@ -779,7 +630,6 @@
                 .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
         verify(mNotificationStackScrollLayoutController)
                 .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
-        reset(mKeyguardStatusViewController);
 
         when(mNotificationPanelViewControllerLazy.get())
                 .thenReturn(mNotificationPanelViewController);
@@ -827,7 +677,6 @@
     public void tearDown() {
         List<Animator> leakedAnimators = null;
         if (mNotificationPanelViewController != null) {
-            mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
             mNotificationPanelViewController.cancelHeightAnimator();
             leakedAnimators = mNotificationPanelViewController.mTestSetOfAnimatorsUsed.stream()
                 .filter(Animator::isRunning).toList();
@@ -841,19 +690,6 @@
         }
     }
 
-    protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
-            int ambientPadding) {
-
-        when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
-        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
-        when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
-        when(mKeyguardRootViewChild.getTop()).thenReturn((int) (stackBottom - lockIconPadding));
-
-        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
-                .thenReturn(indicationPadding);
-        mNotificationPanelViewController.loadDimens();
-    }
-
     protected void triggerPositionClockAndNotifications() {
         mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
     }
@@ -883,16 +719,6 @@
         mNotificationPanelViewController.updateResources();
     }
 
-    protected void updateMultiUserSetting(boolean enabled) {
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
-        final ArgumentCaptor<ContentObserver> observerCaptor =
-                ArgumentCaptor.forClass(ContentObserver.class);
-        verify(mContentResolver)
-                .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
-        observerCaptor.getValue().onChange(/* selfChange */ false);
-    }
-
     protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
         Configuration configuration = new Configuration();
         configuration.smallestScreenWidthDp = smallestScreenWidthDp;
@@ -911,18 +737,6 @@
         );
     }
 
-    protected void assertKeyguardStatusViewCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
-                ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
-    }
-
-    protected void assertKeyguardStatusViewNotCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
-                R.id.qs_edge_guideline);
-    }
-
     protected void setIsFullWidth(boolean fullWidth) {
         float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
         when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 550fcf7..ba989db 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -16,59 +16,28 @@
 
 package com.android.systemui.shade;
 
-import static com.android.keyguard.KeyguardClockSwitch.LARGE;
-import static com.android.keyguard.KeyguardClockSwitch.SMALL;
-import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
-import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPEN;
-import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPENING;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import static com.android.systemui.statusbar.StatusBarState.SHADE;
-import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.graphics.Point;
-import android.os.PowerManager;
-import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
 import android.testing.TestableLooper;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.accessibility.AccessibilityNodeInfo;
 
-import androidx.constraintlayout.widget.ConstraintSet;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.DejankUtils;
 import com.android.systemui.flags.DisableSceneContainer;
-import com.android.systemui.flags.Flags;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
-import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.KeyguardClockPositionAlgorithm;
 
 import com.google.android.msdl.data.model.MSDLToken;
 
@@ -76,10 +45,6 @@
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
-
-import java.util.List;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -91,278 +56,6 @@
         DejankUtils.setImmediate(true);
     }
 
-    /**
-     * When the Back gesture starts (progress 0%), the scrim will stay at 100% scale (1.0f).
-     */
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testBackGesture_min_scrimAtMaxScale() {
-        mNotificationPanelViewController.onBackProgressed(0.0f);
-        verify(mScrimController).applyBackScaling(1.0f);
-    }
-
-    /**
-     * When the Back gesture is at max (progress 100%), the scrim will be scaled to its minimum.
-     */
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testBackGesture_max_scrimAtMinScale() {
-        mNotificationPanelViewController.onBackProgressed(1.0f);
-        verify(mScrimController).applyBackScaling(
-                NotificationPanelViewController.SHADE_BACK_ANIM_MIN_SCALE);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onNotificationHeightChangeWhileOnKeyguardWillComputeMaxKeyguardNotifications() {
-        mStatusBarStateController.setState(KEYGUARD);
-        ArgumentCaptor<OnHeightChangedListener> captor =
-                ArgumentCaptor.forClass(OnHeightChangedListener.class);
-        verify(mNotificationStackScrollLayoutController)
-                .setOnHeightChangedListener(captor.capture());
-        OnHeightChangedListener listener = captor.getValue();
-
-        clearInvocations(mNotificationStackSizeCalculator);
-        listener.onHeightChanged(mock(ExpandableView.class), false);
-
-        verify(mNotificationStackSizeCalculator)
-                .computeMaxKeyguardNotifications(any(), anyFloat(), anyFloat(), anyFloat());
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onNotificationHeightChangeWhileInShadeWillNotComputeMaxKeyguardNotifications() {
-        mStatusBarStateController.setState(SHADE);
-        ArgumentCaptor<OnHeightChangedListener> captor =
-                ArgumentCaptor.forClass(OnHeightChangedListener.class);
-        verify(mNotificationStackScrollLayoutController)
-                .setOnHeightChangedListener(captor.capture());
-        OnHeightChangedListener listener = captor.getValue();
-
-        clearInvocations(mNotificationStackSizeCalculator);
-        listener.onHeightChanged(mock(ExpandableView.class), false);
-
-        verify(mNotificationStackSizeCalculator, never())
-                .computeMaxKeyguardNotifications(any(), anyFloat(), anyFloat(), anyFloat());
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void computeMaxKeyguardNotifications_lockscreenToShade_returnsExistingMax() {
-        when(mAmbientState.getFractionToShade()).thenReturn(0.5f);
-        mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
-
-        // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
-        assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
-                .isEqualTo(-1);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void computeMaxKeyguardNotifications_noTransition_updatesMax() {
-        when(mAmbientState.getFractionToShade()).thenReturn(0f);
-        mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
-
-        // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
-        assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
-                .isNotEqualTo(-1);
-    }
-
-    @Test
-    @Ignore("b/261472011 - Test appears inconsistent across environments")
-    public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
-        setBottomPadding(/* stackScrollLayoutBottom= */ 180,
-                /* lockIconPadding= */ 20,
-                /* indicationPadding= */ 0,
-                /* ambientPadding= */ 0);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenNotifications())
-                .isEqualTo(80);
-    }
-
-    @Test
-    @Ignore("b/261472011 - Test appears inconsistent across environments")
-    public void getVerticalSpaceForLockscreenNotifications_useIndicationBottomPadding_returnsSpaceAvailable() {
-        setBottomPadding(/* stackScrollLayoutBottom= */ 180,
-                /* lockIconPadding= */ 0,
-                /* indicationPadding= */ 30,
-                /* ambientPadding= */ 0);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenNotifications())
-                .isEqualTo(70);
-    }
-
-    @Test
-    @Ignore("b/261472011 - Test appears inconsistent across environments")
-    public void getVerticalSpaceForLockscreenNotifications_useAmbientBottomPadding_returnsSpaceAvailable() {
-        setBottomPadding(/* stackScrollLayoutBottom= */ 180,
-                /* lockIconPadding= */ 0,
-                /* indicationPadding= */ 0,
-                /* ambientPadding= */ 40);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenNotifications())
-                .isEqualTo(60);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getVerticalSpaceForLockscreenShelf_useLockIconBottomPadding_returnsShelfHeight() {
-        enableSplitShade(/* enabled= */ false);
-        setBottomPadding(/* stackScrollLayoutBottom= */ 100,
-                /* lockIconPadding= */ 20,
-                /* indicationPadding= */ 0,
-                /* ambientPadding= */ 0);
-
-        when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(5);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(5);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getVerticalSpaceForLockscreenShelf_useIndicationBottomPadding_returnsZero() {
-        enableSplitShade(/* enabled= */ false);
-        setBottomPadding(/* stackScrollLayoutBottom= */ 100,
-                /* lockIconPadding= */ 0,
-                /* indicationPadding= */ 30,
-                /* ambientPadding= */ 0);
-
-        when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getVerticalSpaceForLockscreenShelf_useAmbientBottomPadding_returnsZero() {
-        enableSplitShade(/* enabled= */ false);
-        setBottomPadding(/* stackScrollLayoutBottom= */ 100,
-                /* lockIconPadding= */ 0,
-                /* indicationPadding= */ 0,
-                /* ambientPadding= */ 40);
-
-        when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getVerticalSpaceForLockscreenShelf_useLockIconPadding_returnsLessThanShelfHeight() {
-        enableSplitShade(/* enabled= */ false);
-        setBottomPadding(/* stackScrollLayoutBottom= */ 100,
-                /* lockIconPadding= */ 10,
-                /* indicationPadding= */ 8,
-                /* ambientPadding= */ 0);
-
-        when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(2);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(2);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getVerticalSpaceForLockscreenShelf_splitShade() {
-        enableSplitShade(/* enabled= */ true);
-        setBottomPadding(/* stackScrollLayoutBottom= */ 100,
-                /* lockIconPadding= */ 10,
-                /* indicationPadding= */ 8,
-                /* ambientPadding= */ 0);
-
-        when(mNotificationStackScrollLayoutController.getShelfHeight()).thenReturn(5);
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-
-        assertThat(mNotificationPanelViewController.getVerticalSpaceForLockscreenShelf())
-                .isEqualTo(0);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSetPanelScrimMinFractionWhenHeadsUpIsDragged() {
-        mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
-                mNotificationPanelViewController.getMaxPanelHeight() / 2);
-        verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSetDozing_notifiesNsslAndStateController() {
-        mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */);
-        verify(mNotificationStackScrollLayoutController).setDozing(eq(true), eq(false));
-        assertThat(mStatusBarStateController.getDozeAmount()).isEqualTo(1f);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testOnDozeAmountChanged_positionClockAndNotificationsUsesUdfpsLocation() {
-        // GIVEN UDFPS is enrolled and we're on the keyguard
-        final Point udfpsLocationCenter = new Point(0, 100);
-        final float udfpsRadius = 10f;
-        when(mUpdateMonitor.isUdfpsEnrolled()).thenReturn(true);
-        when(mAuthController.getUdfpsLocation()).thenReturn(udfpsLocationCenter);
-        when(mAuthController.getUdfpsRadius()).thenReturn(udfpsRadius);
-        mNotificationPanelViewController.getStatusBarStateListener().onStateChanged(KEYGUARD);
-
-        // WHEN the doze amount changes
-        mNotificationPanelViewController.mClockPositionAlgorithm = mock(
-                KeyguardClockPositionAlgorithm.class);
-        mNotificationPanelViewController.getStatusBarStateListener().onDozeAmountChanged(1f, 1f);
-
-        // THEN the clock positions accounts for the UDFPS location & its worst case burn in
-        final float udfpsTop = udfpsLocationCenter.y - udfpsRadius - mMaxUdfpsBurnInOffsetY;
-        verify(mNotificationPanelViewController.mClockPositionAlgorithm).setup(
-                anyInt(),
-                anyFloat(),
-                anyInt(),
-                anyInt(),
-                anyInt(),
-                /* darkAmount */ eq(1f),
-                anyFloat(),
-                anyBoolean(),
-                anyInt(),
-                anyFloat(),
-                anyInt(),
-                anyBoolean(),
-                /* udfpsTop */ eq(udfpsTop),
-                anyFloat(),
-                anyBoolean()
-        );
-    }
-
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSetExpandedHeight() {
-        mNotificationPanelViewController.setExpandedHeight(200);
-        assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testOnTouchEvent_expansionCanBeBlocked() {
-        onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0));
-        onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 200f, 0));
-        assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
-
-        mNotificationPanelViewController.blockExpansionForCurrentTouch();
-        onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 300f, 0));
-        // Expansion should not have changed because it was blocked
-        assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
-    }
-
     @Test
     @EnableFlags(com.android.systemui.Flags.FLAG_SHADE_EXPANDS_ON_STATUS_BAR_LONG_PRESS)
     public void onStatusBarLongPress_shadeExpands() {
@@ -422,71 +115,6 @@
     }
 
     @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void test_pulsing_onTouchEvent_noTracking() {
-        // GIVEN device is pulsing
-        mNotificationPanelViewController.setPulsing(true);
-
-        // WHEN touch DOWN & MOVE events received
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
-                0 /* metaState */));
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 200f /* y */,
-                0 /* metaState */));
-
-        // THEN touch is NOT tracked (since the device is pulsing)
-        assertThat(mNotificationPanelViewController.isTracking()).isFalse();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void alternateBouncerVisible_onTouchEvent_notHandled() {
-        // GIVEN alternate bouncer is visible
-        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
-
-        // WHEN touch DOWN event received; THEN touch is NOT handled
-        assertThat(onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
-                0 /* metaState */))).isFalse();
-
-        // WHEN touch MOVE event received; THEN touch is NOT handled
-        assertThat(onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 200f /* y */,
-                0 /* metaState */))).isFalse();
-
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void test_onTouchEvent_startTracking() {
-        // GIVEN device is NOT pulsing
-        mNotificationPanelViewController.setPulsing(false);
-
-        // WHEN touch DOWN & MOVE events received
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
-                0 /* metaState */));
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 200f /* y */,
-                0 /* metaState */));
-
-        // THEN touch is tracked
-        assertThat(mNotificationPanelViewController.isTracking()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onInterceptTouchEvent_nsslMigrationOff_userActivity() {
-        mTouchHandler.onInterceptTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
-                0 /* metaState */));
-
-        verify(mCentralSurfaces).userActivity();
-    }
-
-    @Test
-    @EnableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     public void onInterceptTouchEvent_nsslMigrationOn_userActivity_not_called() {
         mTouchHandler.onInterceptTouchEvent(MotionEvent.obtain(0L /* downTime */,
                 0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -496,279 +124,6 @@
     }
 
     @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testOnTouchEvent_expansionResumesAfterBriefTouch() {
-        mFalsingManager.setIsClassifierEnabled(true);
-        mFalsingManager.setIsFalseTouch(false);
-        mNotificationPanelViewController.setForceFlingAnimationForTest(true);
-        // Start shade collapse with swipe up
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
-                0 /* metaState */));
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 300f /* y */,
-                0 /* metaState */));
-        onTouchEvent(MotionEvent.obtain(0L /* downTime */,
-                0L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */,
-                0 /* metaState */));
-
-        assertThat(mNotificationPanelViewController.isClosing()).isTrue();
-        assertThat(mNotificationPanelViewController.isFlinging()).isTrue();
-
-        // simulate touch that does not exceed touch slop
-        onTouchEvent(MotionEvent.obtain(2L /* downTime */,
-                2L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 300f /* y */,
-                0 /* metaState */));
-
-        mNotificationPanelViewController.setTouchSlopExceeded(false);
-
-        onTouchEvent(MotionEvent.obtain(2L /* downTime */,
-                2L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */,
-                0 /* metaState */));
-
-        // fling should still be called after a touch that does not exceed touch slop
-        assertThat(mNotificationPanelViewController.isClosing()).isTrue();
-        assertThat(mNotificationPanelViewController.isFlinging()).isTrue();
-        mNotificationPanelViewController.setForceFlingAnimationForTest(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testA11y_initializeNode() {
-        AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
-        mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(mView, nodeInfo);
-
-        List<AccessibilityNodeInfo.AccessibilityAction> actionList = nodeInfo.getActionList();
-        assertThat(actionList).containsAtLeastElementsIn(
-                new AccessibilityNodeInfo.AccessibilityAction[] {
-                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD,
-                        AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP}
-        );
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testA11y_scrollForward() {
-        mAccessibilityDelegate.performAccessibilityAction(
-                mView,
-                AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId(),
-                null);
-
-        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testA11y_scrollUp() {
-        mAccessibilityDelegate.performAccessibilityAction(
-                mView,
-                AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_UP.getId(),
-                null);
-
-        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testKeyguardStatusViewInSplitShade_changesConstraintsDependingOnNotifications() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd)
-                .isEqualTo(R.id.qs_edge_guideline);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd)
-                .isEqualTo(ConstraintSet.PARENT_ID);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_splitShade_dozing_alwaysDozingOn_isCentered() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        setDozing(/* dozing= */ true, /* dozingAlwaysOn= */ true);
-
-        assertKeyguardStatusViewCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_splitShade_dozing_alwaysDozingOff_isNotCentered() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        setDozing(/* dozing= */ true, /* dozingAlwaysOn= */ false);
-
-        assertKeyguardStatusViewNotCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_splitShade_notDozing_alwaysDozingOn_isNotCentered() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ true);
-
-        assertKeyguardStatusViewNotCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_splitShade_pulsing_isNotCentered() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        when(mNotificationListContainer.hasPulsingNotifications()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ false);
-
-        assertKeyguardStatusViewNotCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_splitShade_notPulsing_isNotCentered() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        when(mNotificationListContainer.hasPulsingNotifications()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ false);
-
-        assertKeyguardStatusViewNotCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_singleShade_isCentered() {
-        enableSplitShade(/* enabled= */ false);
-        // The conditions below would make the clock NOT be centered on split shade.
-        // On single shade it should always be centered though.
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        when(mNotificationListContainer.hasPulsingNotifications()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ false);
-
-        assertKeyguardStatusViewCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_willPlayDelayedDoze_isCentered_thenNot() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(true);
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ false);
-        assertKeyguardStatusViewCentered();
-
-        mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(false);
-        assertKeyguardStatusViewNotCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_willPlayDelayedDoze_notifiesKeyguardMediaController() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(true);
-
-        verify(mKeyguardMediaController).setDozeWakeUpAnimationWaiting(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void keyguardStatusView_willPlayDelayedDoze_isCentered_thenStillCenteredIfNoNotifs() {
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-
-        mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(true);
-        setDozing(/* dozing= */ false, /* dozingAlwaysOn= */ false);
-        assertKeyguardStatusViewCentered();
-
-        mNotificationPanelViewController.setWillPlayDelayedDozeAmountAnimation(false);
-        assertKeyguardStatusViewCentered();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onKeyguardStatusViewHeightChange_animatesNextTopPaddingChangeForNSSL() {
-        ArgumentCaptor<View.OnLayoutChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mKeyguardStatusView).addOnLayoutChangeListener(captor.capture());
-        View.OnLayoutChangeListener listener = captor.getValue();
-
-        clearInvocations(mNotificationStackScrollLayoutController);
-
-        when(mKeyguardStatusView.getHeight()).thenReturn(0);
-        listener.onLayoutChange(mKeyguardStatusView, /* left= */ 0, /* top= */ 0, /* right= */
-                0, /* bottom= */ 0, /* oldLeft= */ 0, /* oldTop= */ 0, /* oldRight= */
-                0, /* oldBottom = */ 200);
-
-        verify(mNotificationStackScrollLayoutController).animateNextTopPaddingChange();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
-        mStatusBarStateController.setState(KEYGUARD);
-
-        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testCanCollapsePanelOnTouch_trueWhenScrolledToBottom() {
-        mStatusBarStateController.setState(SHADE);
-        when(mNotificationStackScrollLayoutController.isScrolledToBottom()).thenReturn(true);
-
-        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testCanCollapsePanelOnTouch_trueWhenInSettings() {
-        mStatusBarStateController.setState(SHADE);
-        when(mQsController.getExpanded()).thenReturn(true);
-
-        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testCanCollapsePanelOnTouch_falseInDualPaneShade() {
-        mStatusBarStateController.setState(SHADE);
-        enableSplitShade(/* enabled= */ true);
-        when(mQsController.getExpanded()).thenReturn(true);
-
-        assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isFalse();
-    }
-
-    @Test
     @Ignore("b/341163515 - fails to clean up animators correctly")
     public void testSwipeWhileLocked_notifiesKeyguardState() {
         mStatusBarStateController.setState(KEYGUARD);
@@ -786,515 +141,6 @@
     }
 
     @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testCancelSwipeWhileLocked_notifiesKeyguardState() {
-        mStatusBarStateController.setState(KEYGUARD);
-
-        // Fling expanded (cancelling the keyguard exit swipe). We should notify keyguard state that
-        // the fling occurred and did not dismiss the keyguard.
-        mNotificationPanelViewController.flingToHeight(
-                0f, true /* expand */, 1000f, 1f, false);
-        mNotificationPanelViewController.cancelHeightAnimator();
-        verify(mKeyguardStateController).notifyPanelFlingEnd();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSwipe_exactlyToTarget_notifiesNssl() {
-        // No over-expansion
-        mNotificationPanelViewController.setOverExpansion(0f);
-        // Fling to a target that is equal to the current position (i.e. a no-op fling).
-        mNotificationPanelViewController.flingToHeight(
-                0f,
-                true,
-                mNotificationPanelViewController.getExpandedHeight(),
-                1f,
-                false);
-        // Verify that the NSSL is notified that the panel is *not* flinging.
-        verify(mNotificationStackScrollLayoutController).setPanelFlinging(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testRotatingToSplitShadeWithQsExpanded_transitionsToShadeLocked() {
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mQsController.getExpanded()).thenReturn(true);
-
-        enableSplitShade(true);
-
-        assertThat(mStatusBarStateController.getState()).isEqualTo(SHADE_LOCKED);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testUnlockedSplitShadeTransitioningToKeyguard_closesQS() {
-        enableSplitShade(true);
-        mStatusBarStateController.setState(SHADE);
-        mStatusBarStateController.setState(KEYGUARD);
-
-        verify(mQsController).closeQs();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testLockedSplitShadeTransitioningToKeyguard_closesQS() {
-        enableSplitShade(true);
-        mStatusBarStateController.setState(SHADE_LOCKED);
-        mStatusBarStateController.setState(KEYGUARD);
-
-        verify(mQsController).closeQs();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSwitchesToCorrectClockInSinglePaneShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController).displayClock(SMALL, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSwitchesToCorrectClockInSplitShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        clearInvocations(mKeyguardStatusViewController);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController, times(2))
-                .displayClock(LARGE, /* animate */ true);
-        verify(mKeyguardStatusViewController, never())
-                .displayClock(SMALL, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testHasNotifications_switchesToLargeClockWhenEnteringSplitShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-
-        enableSplitShade(/* enabled= */ true);
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testNoNotifications_switchesToLargeClockWhenEnteringSplitShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-
-        enableSplitShade(/* enabled= */ true);
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testHasNotifications_switchesToSmallClockWhenExitingSplitShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        clearInvocations(mKeyguardStatusViewController);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-
-        enableSplitShade(/* enabled= */ false);
-
-        verify(mKeyguardStatusViewController).displayClock(SMALL, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testNoNotifications_switchesToLargeClockWhenExitingSplitShade() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        clearInvocations(mKeyguardStatusViewController);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-
-        enableSplitShade(/* enabled= */ false);
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void clockSize_mediaShowing_inSplitShade_onAod_isLarge() {
-        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        when(mMediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        clearInvocations(mKeyguardStatusViewController);
-
-        mNotificationPanelViewController.setDozing(/* dozing= */ true, /* animate= */ false);
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate= */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void clockSize_mediaShowing_inSplitShade_screenOff_notAod_isSmall() {
-        when(mDozeParameters.getAlwaysOn()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        when(mMediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        clearInvocations(mKeyguardStatusViewController);
-
-        mNotificationPanelViewController.setDozing(/* dozing= */ true, /* animate= */ false);
-
-        verify(mKeyguardStatusViewController).displayClock(SMALL, /* animate= */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onQsSetExpansionHeightCalled_qsFullyExpandedOnKeyguard_showNSSL() {
-        // GIVEN
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(false);
-        when(mQsController.getFullyExpanded()).thenReturn(true);
-        when(mQsController.getExpanded()).thenReturn(true);
-
-        // WHEN
-        int transitionDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-
-        // THEN
-        // We are interested in the last value of the stack alpha.
-        ArgumentCaptor<Float> alphaCaptor = ArgumentCaptor.forClass(Float.class);
-        verify(mNotificationStackScrollLayoutController, atLeastOnce())
-                .setMaxAlphaForKeyguard(alphaCaptor.capture(), any());
-        assertThat(alphaCaptor.getValue()).isEqualTo(1.0f);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onQsSetExpansionHeightCalled_qsFullyExpandedOnKeyguard_hideNSSL() {
-        // GIVEN
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(false);
-        when(mQsController.getFullyExpanded()).thenReturn(false);
-        when(mQsController.getExpanded()).thenReturn(true);
-
-        // WHEN
-        int transitionDistance = mNotificationPanelViewController
-                .getMaxPanelTransitionDistance() / 2;
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-
-        // THEN
-        // We are interested in the last value of the stack alpha.
-        ArgumentCaptor<Float> alphaCaptor = ArgumentCaptor.forClass(Float.class);
-        verify(mNotificationStackScrollLayoutController, atLeastOnce())
-                .setMaxAlphaForKeyguard(alphaCaptor.capture(), any());
-        assertThat(alphaCaptor.getValue()).isEqualTo(0.0f);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testSwitchesToBigClockInSplitShadeOnAodAnimateDisabled() {
-        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        clearInvocations(mKeyguardStatusViewController);
-        when(mMediaDataManager.hasActiveMedia()).thenReturn(true);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-
-        mNotificationPanelViewController.setDozing(true, false);
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void switchesToBigClockInSplitShadeOn_landFlagOn_ForceSmallClock() {
-        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ false);
-        mNotificationPanelViewController.setDozing(false, false);
-        mFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, true);
-        when(mResources.getBoolean(R.bool.force_small_clock_on_lockscreen)).thenReturn(true);
-        when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        clearInvocations(mKeyguardStatusViewController);
-
-        enableSplitShade(/* enabled= */ true);
-        mNotificationPanelViewController.updateResources();
-
-        verify(mKeyguardStatusViewController).displayClock(SMALL, /* animate */ false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void switchesToBigClockInSplitShadeOn_landFlagOff_DontForceSmallClock() {
-        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(false);
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ false);
-        mNotificationPanelViewController.setDozing(false, false);
-        mFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false);
-        when(mResources.getBoolean(R.bool.force_small_clock_on_lockscreen)).thenReturn(true);
-        when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        clearInvocations(mKeyguardStatusViewController);
-
-        enableSplitShade(/* enabled= */ true);
-        mNotificationPanelViewController.updateResources();
-
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testDisplaysSmallClockOnLockscreenInSplitShadeWhenMediaIsPlaying() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(/* enabled= */ true);
-        clearInvocations(mKeyguardStatusViewController);
-        when(mMediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true);
-
-        // one notification + media player visible
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(true);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController).displayClock(SMALL, /* animate */ true);
-
-        // only media player visible
-        when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
-        when(mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()).thenReturn(false);
-        triggerPositionClockAndNotifications();
-        verify(mKeyguardStatusViewController, times(2)).displayClock(SMALL, true);
-        verify(mKeyguardStatusViewController, never()).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testFoldToAodAnimationCleansupInAnimationEnd() {
-        ArgumentCaptor<Animator.AnimatorListener> animCaptor =
-                ArgumentCaptor.forClass(Animator.AnimatorListener.class);
-        ArgumentCaptor<ValueAnimator.AnimatorUpdateListener> updateCaptor =
-                ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class);
-
-        // Start fold animation & Capture Listeners
-        mNotificationPanelViewController.getShadeFoldAnimator()
-                .startFoldToAodAnimation(() -> {}, () -> {}, () -> {});
-        verify(mViewPropertyAnimator).setListener(animCaptor.capture());
-        verify(mViewPropertyAnimator).setUpdateListener(updateCaptor.capture());
-
-        // End animation and validate listeners were unset
-        animCaptor.getValue().onAnimationEnd(null);
-        verify(mViewPropertyAnimator).setListener(null);
-        verify(mViewPropertyAnimator).setUpdateListener(null);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testExpandWithQsMethodIsUsingLockscreenTransitionController() {
-        enableSplitShade(/* enabled= */ true);
-        mStatusBarStateController.setState(KEYGUARD);
-
-        mNotificationPanelViewController.expandToQs();
-
-        verify(mLockscreenShadeTransitionController).goToLockedShade(
-                /* expandedView= */null, /* needsQSAnimation= */true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void setKeyguardStatusBarAlpha_setsAlphaOnKeyguardStatusBarController() {
-        float statusBarAlpha = 0.5f;
-
-        mNotificationPanelViewController.setKeyguardStatusBarAlpha(statusBarAlpha);
-
-        verify(mKeyguardStatusBarViewController).setAlpha(statusBarAlpha);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testQsToBeImmediatelyExpandedWhenOpeningPanelInSplitShade() {
-        enableSplitShade(/* enabled= */ true);
-        mShadeExpansionStateManager.updateState(STATE_OPEN);
-        verify(mQsController).setExpandImmediate(false);
-
-        mShadeExpansionStateManager.updateState(STATE_CLOSED);
-        verify(mQsController, times(2)).setExpandImmediate(false);
-
-        mShadeExpansionStateManager.updateState(STATE_OPENING);
-        verify(mQsController).setExpandImmediate(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testQsNotToBeImmediatelyExpandedWhenGoingFromUnlockedToLocked() {
-        enableSplitShade(/* enabled= */ true);
-        mShadeExpansionStateManager.updateState(STATE_CLOSED);
-
-        mStatusBarStateController.setState(KEYGUARD);
-        // going to lockscreen would trigger STATE_OPENING
-        mShadeExpansionStateManager.updateState(STATE_OPENING);
-
-        verify(mQsController, never()).setExpandImmediate(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testQsImmediateResetsWhenPanelOpensOrCloses() {
-        mShadeExpansionStateManager.updateState(STATE_OPEN);
-        mShadeExpansionStateManager.updateState(STATE_CLOSED);
-        verify(mQsController, times(2)).setExpandImmediate(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testQsExpansionChangedToDefaultWhenRotatingFromOrToSplitShade() {
-        when(mCommandQueue.panelsEnabled()).thenReturn(true);
-
-        // to make sure shade is in expanded state
-        mNotificationPanelViewController.startInputFocusTransfer();
-
-        // switch to split shade from portrait (default state)
-        enableSplitShade(/* enabled= */ true);
-        verify(mQsController).setExpanded(true);
-
-        // switch to portrait from split shade
-        enableSplitShade(/* enabled= */ false);
-        verify(mQsController).setExpanded(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void testPanelClosedWhenClosingQsInSplitShade() {
-        mShadeExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1,
-                /* expanded= */ true, /* tracking= */ false);
-        enableSplitShade(/* enabled= */ true);
-        mNotificationPanelViewController.setExpandedFraction(1f);
-
-        assertThat(mNotificationPanelViewController.isClosing()).isFalse();
-        mNotificationPanelViewController.animateCollapseQs(false);
-
-        assertThat(mNotificationPanelViewController.isClosing()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
-        enableSplitShade(true);
-        mNotificationPanelViewController.expandToQs();
-
-        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-
-        assertThat(maxDistance).isEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void isExpandingOrCollapsing_returnsTrue_whenQsLockscreenDragInProgress() {
-        when(mQsController.getLockscreenShadeDragProgress()).thenReturn(0.5f);
-        assertThat(mNotificationPanelViewController.isExpandingOrCollapsing()).isTrue();
-    }
-
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() {
-        enableSplitShade(true);
-        mNotificationPanelViewController.expandToQs();
-        when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true);
-        when(mQsController.calculatePanelHeightExpanded(anyInt())).thenReturn(10000);
-        mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
-                SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-
-        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-
-        // make sure we're ignoring the placeholder value for Qs max height
-        assertThat(maxDistance).isLessThan(10000);
-        assertThat(maxDistance).isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getMaxPanelTransitionDistance_expandingSplitShade_keyguard_returnsNonSplitShadeValue() {
-        mStatusBarStateController.setState(KEYGUARD);
-        enableSplitShade(true);
-        mNotificationPanelViewController.expandToQs();
-
-        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-
-        assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getMaxPanelTransitionDistance_expanding_notSplitShade_returnsNonSplitShadeValue() {
-        enableSplitShade(false);
-        mNotificationPanelViewController.expandToQs();
-
-        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-
-        assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onLayoutChange_fullWidth_updatesQSWithFullWithTrue() {
-        setIsFullWidth(true);
-
-        verify(mQsController).setNotificationPanelFullWidth(true);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onLayoutChange_notFullWidth_updatesQSWithFullWithFalse() {
-        setIsFullWidth(false);
-
-        verify(mQsController).setNotificationPanelFullWidth(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onLayoutChange_qsNotSet_doesNotCrash() {
-        mQuickSettingsController.setQs(null);
-
-        triggerLayoutChange();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onEmptySpaceClicked_notDozingAndOnKeyguard_requestsFaceAuth() {
-        StatusBarStateController.StateListener statusBarStateListener =
-                mNotificationPanelViewController.getStatusBarStateListener();
-        statusBarStateListener.onStateChanged(KEYGUARD);
-        mNotificationPanelViewController.setDozing(false, false);
-
-        // This sets the dozing state that is read when onMiddleClicked is eventually invoked.
-        mTouchHandler.onTouch(mock(View.class), mDownMotionEvent);
-        mEmptySpaceClickListenerCaptor.getValue().onEmptySpaceClicked(0, 0);
-
-        verify(mDeviceEntryFaceAuthInteractor).onNotificationPanelClicked();
-    }
-
-    @Test
-    @EnableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     public void nsslFlagEnabled_allowOnlyExternalTouches() {
 
         // This sets the dozing state that is read when onMiddleClicked is eventually invoked.
@@ -1306,130 +152,6 @@
     }
 
     @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onSplitShadeChanged_duringShadeExpansion_resetsOverScrollState() {
-        // There was a bug where there was left-over overscroll state after going from split shade
-        // to single shade.
-        // Since on single shade we don't set overscroll values on QS nor Scrim, those values that
-        // were there from split shade were never reset.
-        // To prevent this, we will reset all overscroll state.
-        enableSplitShade(true);
-        reset(mQsController, mScrimController, mNotificationStackScrollLayoutController);
-
-        mNotificationPanelViewController.setOverExpansion(123);
-        verify(mQsController).setOverScrollAmount(123);
-        verify(mScrimController).setNotificationsOverScrollAmount(123);
-        verify(mNotificationStackScrollLayoutController).setOverExpansion(123);
-
-        enableSplitShade(false);
-        verify(mQsController).setOverScrollAmount(0);
-        verify(mScrimController).setNotificationsOverScrollAmount(0);
-        verify(mNotificationStackScrollLayoutController).setOverExpansion(0);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onSplitShadeChanged_alwaysResetsOverScrollState() {
-        enableSplitShade(true);
-        enableSplitShade(false);
-
-        verify(mQsController, times(2)).setOverScrollAmount(0);
-        verify(mScrimController, times(2)).setNotificationsOverScrollAmount(0);
-        verify(mNotificationStackScrollLayoutController, times(2)).setOverExpansion(0);
-        verify(mNotificationStackScrollLayoutController, times(2)).setOverScrollAmount(0);
-    }
-
-    /**
-     * When shade is flinging to close and this fling is not intercepted,
-     * {@link AmbientState#setIsClosing(boolean)} should be called before
-     * {@link NotificationStackScrollLayoutController#onExpansionStopped()}
-     * to ensure scrollY can be correctly set to be 0
-     */
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onShadeFlingClosingEnd_mAmbientStateSetClose_thenOnExpansionStopped() {
-        // Given: Shade is expanded
-        mNotificationPanelViewController.notifyExpandingFinished();
-        mNotificationPanelViewController.setClosing(false);
-
-        // When: Shade flings to close not canceled
-        mNotificationPanelViewController.notifyExpandingStarted();
-        mNotificationPanelViewController.setClosing(true);
-        mNotificationPanelViewController.onFlingEnd(false);
-
-        // Then: AmbientState's mIsClosing should be set to false
-        // before mNotificationStackScrollLayoutController.onExpansionStopped() is called
-        // to ensure NotificationStackScrollLayout.resetScrollPosition() -> resetScrollPosition
-        // -> setOwnScrollY(0) can set scrollY to 0 when shade is closed
-        InOrder inOrder = inOrder(mAmbientState, mNotificationStackScrollLayoutController);
-        inOrder.verify(mAmbientState).setIsClosing(false);
-        inOrder.verify(mNotificationStackScrollLayoutController).onExpansionStopped();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onShadeFlingEnd_mExpandImmediateShouldBeReset() {
-        mNotificationPanelViewController.onFlingEnd(false);
-
-        verify(mQsController).setExpandImmediate(false);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void inUnlockedSplitShade_transitioningMaxTransitionDistance_makesShadeFullyExpanded() {
-        mStatusBarStateController.setState(SHADE);
-        enableSplitShade(true);
-        int transitionDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-        assertThat(mNotificationPanelViewController.isFullyExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeFullyExpanded_inShadeState() {
-        mStatusBarStateController.setState(SHADE);
-
-        mNotificationPanelViewController.setExpandedHeight(0);
-        assertThat(mNotificationPanelViewController.isShadeFullyExpanded()).isFalse();
-
-        int transitionDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-        assertThat(mNotificationPanelViewController.isShadeFullyExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeFullyExpanded_onKeyguard() {
-        mStatusBarStateController.setState(KEYGUARD);
-
-        int transitionDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-        assertThat(mNotificationPanelViewController.isShadeFullyExpanded()).isFalse();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeFullyExpanded_onShadeLocked() {
-        mStatusBarStateController.setState(SHADE_LOCKED);
-        assertThat(mNotificationPanelViewController.isShadeFullyExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeExpanded_whenHasHeight() {
-        int transitionDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
-        mNotificationPanelViewController.setExpandedHeight(transitionDistance);
-        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeExpanded_whenInstantExpanding() {
-        mNotificationPanelViewController.expand(true);
-        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
-    }
-
-    @Test
     @DisableSceneContainer
     public void shadeExpanded_whenHunIsPresent() {
         when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
@@ -1437,84 +159,6 @@
     }
 
     @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeExpanded_whenUnlockedOffscreenAnimationRunning() {
-        when(mUnlockedScreenOffAnimationController.isAnimationPlaying()).thenReturn(true);
-        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeExpanded_whenInputFocusTransferStarted() {
-        when(mCommandQueue.panelsEnabled()).thenReturn(true);
-
-        mNotificationPanelViewController.startInputFocusTransfer();
-
-        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void shadeNotExpanded_whenInputFocusTransferStartedButPanelsDisabled() {
-        when(mCommandQueue.panelsEnabled()).thenReturn(false);
-
-        mNotificationPanelViewController.startInputFocusTransfer();
-
-        assertThat(mNotificationPanelViewController.isExpanded()).isFalse();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void cancelInputFocusTransfer_shadeCollapsed() {
-        when(mCommandQueue.panelsEnabled()).thenReturn(true);
-        mNotificationPanelViewController.startInputFocusTransfer();
-
-        mNotificationPanelViewController.cancelInputFocusTransfer();
-
-        assertThat(mNotificationPanelViewController.isExpanded()).isFalse();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void finishInputFocusTransfer_shadeFlingingOpen() {
-        when(mCommandQueue.panelsEnabled()).thenReturn(true);
-        mNotificationPanelViewController.startInputFocusTransfer();
-
-        mNotificationPanelViewController.finishInputFocusTransfer(/* velocity= */ 0f);
-
-        assertThat(mNotificationPanelViewController.isFlinging()).isTrue();
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getFalsingThreshold_deviceNotInteractive_isQsThreshold() {
-        PowerInteractor.Companion.setAsleepForTest(
-                mPowerInteractor, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
-        when(mQsController.getFalsingThreshold()).thenReturn(14);
-
-        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isEqualTo(14);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getFalsingThreshold_lastWakeNotDueToTouch_isQsThreshold() {
-        PowerInteractor.Companion.setAwakeForTest(
-                mPowerInteractor, PowerManager.WAKE_REASON_POWER_BUTTON);
-        when(mQsController.getFalsingThreshold()).thenReturn(14);
-
-        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isEqualTo(14);
-    }
-
-    @Test
-    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void getFalsingThreshold_lastWakeDueToTouch_greaterThanQsThreshold() {
-        PowerInteractor.Companion.setAwakeForTest(mPowerInteractor, PowerManager.WAKE_REASON_TAP);
-        when(mQsController.getFalsingThreshold()).thenReturn(14);
-
-        assertThat(mNotificationPanelViewController.getFalsingThreshold()).isGreaterThan(14);
-    }
-
-    @Test
     @EnableFlags(com.android.systemui.Flags.FLAG_MSDL_FEEDBACK)
     public void performHapticFeedback_withMSDL_forGestureStart_deliversDragThresholdToken() {
         mNotificationPanelViewController
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
deleted file mode 100644
index 5289554..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
+++ /dev/null
@@ -1,217 +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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.shade
-
-import android.platform.test.annotations.DisableFlags
-import android.testing.TestableLooper
-import android.view.HapticFeedbackConstants
-import android.view.View
-import android.view.ViewStub
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.util.CollectionUtils
-import com.android.keyguard.KeyguardClockSwitch.LARGE
-import com.android.systemui.Flags
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.StatusBarState.KEYGUARD
-import com.android.systemui.statusbar.StatusBarState.SHADE
-import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.cancelChildren
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.test.advanceUntilIdle
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Captor
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-
-@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-@DisableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-class NotificationPanelViewControllerWithCoroutinesTest :
-    NotificationPanelViewControllerBaseTest() {
-
-    @Captor private lateinit var viewCaptor: ArgumentCaptor<View>
-
-    override fun getMainDispatcher() = Dispatchers.Main.immediate
-
-    @Test
-    fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
-        launch(Dispatchers.Main.immediate) { givenViewAttached() }
-        advanceUntilIdle()
-
-        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
-            .thenReturn(true)
-        updateMultiUserSetting(true)
-        clearInvocations(mView)
-
-        updateMultiUserSetting(false)
-
-        verify(mView, atLeastOnce()).addView(viewCaptor.capture(), anyInt())
-        val userSwitcherStub =
-            CollectionUtils.find(viewCaptor.allValues) { view ->
-                view.id == R.id.keyguard_user_switcher_stub
-            }
-        assertThat(userSwitcherStub).isNotNull()
-        assertThat(userSwitcherStub).isInstanceOf(ViewStub::class.java)
-    }
-
-    @Test
-    fun testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() = runTest {
-        launch(Dispatchers.Main.immediate) { givenViewAttached() }
-        advanceUntilIdle()
-
-        whenever(mView.findViewById<View>(R.id.keyguard_user_switcher_view)).thenReturn(null)
-        updateSmallestScreenWidth(300)
-        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
-            .thenReturn(true)
-        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
-            .thenReturn(false)
-        whenever(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true)
-
-        updateSmallestScreenWidth(800)
-
-        verify(mUserSwitcherStubView).inflate()
-    }
-
-    @Test
-    fun testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() = runTest {
-        launch(Dispatchers.Main.immediate) { givenViewAttached() }
-        advanceUntilIdle()
-
-        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
-            .thenReturn(true)
-        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
-            .thenReturn(false)
-        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-            .thenReturn(false)
-
-        mNotificationPanelViewController.onFinishInflate()
-
-        verify(mUserSwitcherStubView, never()).inflate()
-        verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true)
-
-        coroutineContext.cancelChildren()
-    }
-
-    @Test
-    fun testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() = runTest {
-        launch(Dispatchers.Main.immediate) { givenViewAttached() }
-        advanceUntilIdle()
-
-        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
-            .thenReturn(true)
-        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
-            .thenReturn(false)
-        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-            .thenReturn(false)
-
-        mNotificationPanelViewController.reInflateViews()
-
-        verify(mUserSwitcherStubView, never()).inflate()
-
-        coroutineContext.cancelChildren()
-    }
-
-    @Test
-    fun testDoubleTapRequired_Keyguard() = runTest {
-        launch(Dispatchers.Main.immediate) {
-            val listener = getFalsingTapListener()
-            mStatusBarStateController.setState(KEYGUARD)
-
-            listener.onAdditionalTapRequired()
-
-            verify(mKeyguardIndicationController).showTransientIndication(anyInt())
-        }
-        advanceUntilIdle()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
-    fun doubleTapRequired_onKeyguard_usesPerformHapticFeedback() = runTest {
-        launch(Dispatchers.Main.immediate) {
-            val listener = getFalsingTapListener()
-            mStatusBarStateController.setState(KEYGUARD)
-
-            listener.onAdditionalTapRequired()
-            verify(mKeyguardIndicationController).showTransientIndication(anyInt())
-            verify(mVibratorHelper)
-                .performHapticFeedback(eq(mView), eq(HapticFeedbackConstants.REJECT))
-        }
-        advanceUntilIdle()
-    }
-
-    @Test
-    fun testDoubleTapRequired_ShadeLocked() = runTest {
-        launch(Dispatchers.Main.immediate) {
-            val listener = getFalsingTapListener()
-            mStatusBarStateController.setState(SHADE_LOCKED)
-
-            listener.onAdditionalTapRequired()
-
-            verify(mTapAgainViewController).show()
-        }
-        advanceUntilIdle()
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
-    fun doubleTapRequired_shadeLocked_usesPerformHapticFeedback() = runTest {
-        launch(Dispatchers.Main.immediate) {
-            val listener = getFalsingTapListener()
-            mStatusBarStateController.setState(SHADE_LOCKED)
-
-            listener.onAdditionalTapRequired()
-            verify(mVibratorHelper)
-                .performHapticFeedback(eq(mView), eq(HapticFeedbackConstants.REJECT))
-
-            verify(mTapAgainViewController).show()
-        }
-        advanceUntilIdle()
-    }
-
-    @Test
-    fun testOnAttachRefreshStatusBarState() = runTest {
-        launch(Dispatchers.Main.immediate) {
-            mStatusBarStateController.setState(KEYGUARD)
-            whenever(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false)
-            mOnAttachStateChangeListeners.forEach { it.onViewAttachedToWindow(mView) }
-            verify(mKeyguardStatusViewController)
-                .setKeyguardStatusViewVisibility(
-                    KEYGUARD /*statusBarState*/,
-                    false /*keyguardFadingAway*/,
-                    false /*goingToFullShade*/,
-                    SHADE, /*oldStatusBarState*/
-                )
-        }
-        advanceUntilIdle()
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 929537dc..ee9cb14 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -16,10 +16,10 @@
 package com.android.systemui.shade
 
 import android.content.res.Configuration
-import android.os.SystemClock
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.testing.TestableLooper.RunWithLooper
+import android.view.Choreographer
 import android.view.MotionEvent
 import android.widget.FrameLayout
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -46,6 +46,7 @@
 import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.statusbar.BlurUtils
 import com.android.systemui.statusbar.DragDownHelper
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
 import com.android.systemui.statusbar.NotificationInsetsController
@@ -68,6 +69,7 @@
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.window.ui.viewmodel.WindowRootViewModel
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -93,6 +95,9 @@
 @SmallTest
 class NotificationShadeWindowViewTest : SysuiTestCase() {
 
+    @Mock private lateinit var choreographer: Choreographer
+    @Mock private lateinit var blurUtils: BlurUtils
+    @Mock private lateinit var windowRootViewModelFactory: WindowRootViewModel.Factory
     @Mock private lateinit var dragDownHelper: DragDownHelper
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
     @Mock private lateinit var shadeController: ShadeController
@@ -170,6 +175,9 @@
         testScope = TestScope()
         controller =
             NotificationShadeWindowViewController(
+                blurUtils,
+                windowRootViewModelFactory,
+                choreographer,
                 lockscreenShadeTransitionController,
                 FalsingCollectorFake(),
                 statusBarStateController,
@@ -212,18 +220,6 @@
     }
 
     @Test
-    @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testDragDownHelperCalledWhenDraggingDown() =
-        testScope.runTest {
-            whenever(dragDownHelper.isDraggingDown).thenReturn(true)
-            val now = SystemClock.elapsedRealtime()
-            val ev = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0f, 0f, 0 /* meta */)
-            underTest.onTouchEvent(ev)
-            verify(dragDownHelper).onTouchEvent(ev)
-            ev.recycle()
-        }
-
-    @Test
     fun testNoInterceptTouch() =
         testScope.runTest {
             captureInteractionEventHandler()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index b58c13c..7433267 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
-import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
@@ -200,9 +199,6 @@
                 ),
                 mKosmos.getShadeModeInteractor());
 
-        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
-        keyguardStatusView.setId(R.id.keyguard_status_view);
-
         when(mResources.getDimensionPixelSize(
                 R.dimen.lockscreen_shade_qs_transition_distance)).thenReturn(DEFAULT_HEIGHT);
         when(mPanelView.getResources()).thenReturn(mResources);
@@ -218,8 +214,6 @@
         when(mQs.getHeaderBottom()).thenReturn(QS_FRAME_BOTTOM);
         when(mPanelView.getY()).thenReturn((float) QS_FRAME_TOP);
         when(mPanelView.getHeight()).thenReturn(QS_FRAME_BOTTOM);
-        when(mPanelView.findViewById(R.id.keyguard_status_view))
-                .thenReturn(mock(KeyguardStatusView.class));
         when(mQs.getView()).thenReturn(mPanelView);
         when(mQSFragment.getView()).thenReturn(mPanelView);
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerTest.kt
new file mode 100644
index 0000000..56356b4
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerTest.kt
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.latencyTracker
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.view.fakeChoreographerUtils
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.testKosmos
+import kotlin.test.Test
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.any
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ShadeDisplayChangeLatencyTrackerTest : SysuiTestCase() {
+    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
+    private val configurationRepository = kosmos.fakeConfigurationRepository
+    private val latencyTracker = kosmos.latencyTracker
+    private val testScope = kosmos.testScope
+    private val choreographerUtils = kosmos.fakeChoreographerUtils
+
+    private val underTest = kosmos.shadeDisplayChangeLatencyTracker
+
+    @Test
+    fun onShadeDisplayChanging_afterMovedToDisplayAndDoFrameCompleted_atomReported() =
+        testScope.runTest {
+            underTest.onShadeDisplayChanging(1)
+
+            verify(latencyTracker).onActionStart(any())
+            verify(latencyTracker, never()).onActionEnd(any())
+
+            sendOnMovedToDisplay(1)
+            choreographerUtils.completeDoFrame()
+
+            verify(latencyTracker).onActionEnd(any())
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun onChange_doFrameTimesOut_previousCancelled() =
+        testScope.runTest {
+            underTest.onShadeDisplayChanging(1)
+
+            verify(latencyTracker).onActionStart(any())
+            verify(latencyTracker, never()).onActionEnd(any())
+
+            sendOnMovedToDisplay(1)
+            advanceTimeBy(100.seconds)
+
+            verify(latencyTracker, never()).onActionEnd(any())
+            verify(latencyTracker).onActionCancel(any())
+        }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun onChange_onMovedToDisplayTimesOut_cancelled() =
+        testScope.runTest {
+            underTest.onShadeDisplayChanging(1)
+
+            verify(latencyTracker).onActionStart(any())
+
+            choreographerUtils.completeDoFrame()
+            advanceTimeBy(100.seconds)
+
+            verify(latencyTracker).onActionCancel(any())
+        }
+
+    @Test
+    fun onChange_whilePreviousWasInProgress_previousCancelledAndNewStarted() =
+        testScope.runTest {
+            underTest.onShadeDisplayChanging(1)
+
+            verify(latencyTracker).onActionStart(any())
+
+            underTest.onShadeDisplayChanging(2)
+
+            verify(latencyTracker).onActionCancel(any())
+            verify(latencyTracker, times(2)).onActionStart(any())
+        }
+
+    @Test
+    fun onChange_multiple_multipleReported() =
+        testScope.runTest {
+            underTest.onShadeDisplayChanging(1)
+            verify(latencyTracker).onActionStart(any())
+
+            sendOnMovedToDisplay(1)
+            choreographerUtils.completeDoFrame()
+
+            verify(latencyTracker).onActionEnd(any())
+
+            underTest.onShadeDisplayChanging(0)
+
+            sendOnMovedToDisplay(0)
+            choreographerUtils.completeDoFrame()
+
+            verify(latencyTracker, times(2)).onActionStart(any())
+            verify(latencyTracker, times(2)).onActionEnd(any())
+        }
+
+    private fun sendOnMovedToDisplay(displayId: Int) {
+        configurationRepository.onMovedToDisplay(displayId)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
index e93d0ef..a98d1a2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
@@ -45,6 +45,7 @@
     private val positionRepository = kosmos.fakeShadeDisplaysRepository
     private val shadeContext = kosmos.mockedWindowContext
     private val resources = kosmos.mockResources
+    private val latencyTracker = kosmos.mockedShadeDisplayChangeLatencyTracker
     private val configuration = mock<Configuration>()
     private val display = mock<Display>()
 
@@ -81,4 +82,14 @@
 
         verify(shadeContext).reparentToDisplay(eq(1))
     }
+
+    @Test
+    fun start_shadeInWrongPosition_logsStartToLatencyTracker() {
+        whenever(display.displayId).thenReturn(0)
+        positionRepository.setDisplayId(1)
+
+        underTest.start()
+
+        verify(latencyTracker).onShadeDisplayChanging(eq(1))
+    }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt
index ad2b23e..a47db2e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt
@@ -118,12 +118,12 @@
         }
 
     @Test
-    fun getTopEdgeSplitFraction_wideScreen_leftSideLarger() =
+    fun getTopEdgeSplitFraction_wideScreen_splitInHalf() =
         testScope.runTest {
             // Ensure isShadeLayoutWide is collected.
             val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
             kosmos.shadeRepository.setShadeLayoutWide(true)
 
-            assertThat(underTest.getTopEdgeSplitFraction()).isGreaterThan(0.5f)
+            assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f)
         }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
index aa8b4f1..4423426 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/DefaultClockProviderTest.kt
@@ -117,7 +117,6 @@
         verify(mockLargeClockView).onTimeZoneChanged(notNull())
         verify(mockSmallClockView).refreshTime()
         verify(mockLargeClockView).refreshTime()
-        verify(mockLargeClockView).setLayoutParams(any())
     }
 
     @Test
@@ -163,7 +162,6 @@
         clock.largeClock.events.onFontSettingChanged(200f)
 
         verify(mockLargeClockView).setTextSize(eq(TypedValue.COMPLEX_UNIT_PX), eq(200f))
-        verify(mockLargeClockView).setLayoutParams(any())
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
index ef03fab..d92781a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shared/system/QuickStepContractTest.kt
@@ -16,8 +16,10 @@
 
 package com.android.systemui.shared.system
 
+import android.platform.test.annotations.DisableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BACK_ACTION
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_COMMUNAL_HUB_SHOWING
@@ -30,6 +32,7 @@
 @RunWith(AndroidJUnit4::class)
 class QuickStepContractTest : SysuiTestCase() {
     @Test
+    @DisableFlags(FLAG_GLANCEABLE_HUB_BACK_ACTION)
     fun isBackGestureDisabled_hubShowing() {
         val sysuiStateFlags = SYSUI_STATE_COMMUNAL_HUB_SHOWING
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
index d0ba629..e7b6e4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar
 
-import android.content.res.Resources
 import android.view.CrossWindowBlurListeners
 import android.view.SurfaceControl
 import android.view.ViewRootImpl
@@ -24,11 +23,11 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.clearInvocations
@@ -36,13 +35,14 @@
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class BlurUtilsTest : SysuiTestCase() {
 
-    @Mock lateinit var resources: Resources
+    val blurConfig: BlurConfig = BlurConfig(minBlurRadiusPx = 1.0f, maxBlurRadiusPx = 100.0f)
     @Mock lateinit var dumpManager: DumpManager
     @Mock lateinit var transaction: SurfaceControl.Transaction
     @Mock lateinit var crossWindowBlurListeners: CrossWindowBlurListeners
@@ -109,7 +109,7 @@
         verify(transaction).setEarlyWakeupEnd()
     }
 
-    inner class TestableBlurUtils : BlurUtils(resources, crossWindowBlurListeners, dumpManager) {
+    inner class TestableBlurUtils : BlurUtils(blurConfig, crossWindowBlurListeners, dumpManager) {
         var blursEnabled = true
 
         override fun supportsBlursOnWindows(): Boolean {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 9f94cff..2d7dc2e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -17,15 +17,19 @@
 package com.android.systemui.statusbar
 
 import android.os.IBinder
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import android.testing.TestableLooper.RunWithLooper
 import android.view.Choreographer
 import android.view.View
 import android.view.ViewRootImpl
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
 import com.android.systemui.shade.ShadeExpansionChangeEvent
@@ -35,8 +39,10 @@
 import com.android.systemui.statusbar.policy.FakeConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
+import com.android.systemui.testKosmos
 import com.android.systemui.util.WallpaperController
 import com.android.systemui.util.mockito.eq
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
 import com.google.common.truth.Truth.assertThat
 import java.util.function.Consumer
 import org.junit.Before
@@ -44,6 +50,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.floatThat
 import org.mockito.Captor
@@ -63,7 +70,10 @@
 @RunWithLooper
 @SmallTest
 class NotificationShadeDepthControllerTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
 
+    private val applicationScope = kosmos.testScope.backgroundScope
+    @Mock private lateinit var windowRootViewBlurInteractor: WindowRootViewBlurInteractor
     @Mock private lateinit var statusBarStateController: StatusBarStateController
     @Mock private lateinit var blurUtils: BlurUtils
     @Mock private lateinit var biometricUnlockController: BiometricUnlockController
@@ -101,8 +111,8 @@
             answer.arguments[0] as Float / maxBlur.toFloat()
         }
         `when`(blurUtils.supportsBlursOnWindows()).thenReturn(true)
-        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
-        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
+        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur.toFloat())
+        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur.toFloat())
 
         notificationShadeDepthController =
             NotificationShadeDepthController(
@@ -115,9 +125,12 @@
                 notificationShadeWindowController,
                 dozeParameters,
                 context,
-                    ResourcesSplitShadeStateController(),
+                ResourcesSplitShadeStateController(),
+                windowRootViewBlurInteractor,
+                applicationScope,
                 dumpManager,
-                configurationController,)
+                configurationController,
+            )
         notificationShadeDepthController.shadeAnimation = shadeAnimation
         notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring
         notificationShadeDepthController.root = root
@@ -309,8 +322,8 @@
         `when`(blurUtils.ratioOfBlurRadius(anyFloat())).then { answer ->
             answer.arguments[0] as Float / maxBlur.toFloat()
         }
-        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
-        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur)
+        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur.toFloat())
+        `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur.toFloat())
 
         notificationShadeDepthController.transitionToFullShadeProgress = 1f
         notificationShadeDepthController.updateBlurCallback.doFrame(0)
@@ -356,6 +369,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_BOUNCER_UI_REVAMP)
     fun ignoreShadeBlurUntilHidden_schedulesFrame() {
         notificationShadeDepthController.blursDisabledForAppLaunch = true
         verify(blurUtils).prepareBlur(any(), anyInt())
@@ -364,6 +378,13 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_BOUNCER_UI_REVAMP)
+    fun ignoreShadeBlurUntilHidden_requestsBlur_windowBlurFlag() {
+        notificationShadeDepthController.blursDisabledForAppLaunch = true
+        verify(windowRootViewBlurInteractor).requestBlurForShade(anyInt(), anyBoolean())
+    }
+
+    @Test
     fun ignoreBlurForUnlock_ignores() {
         notificationShadeDepthController.onPanelExpansionChanged(
             ShadeExpansionChangeEvent(
@@ -410,6 +431,7 @@
     }
 
     @Test
+    @DisableFlags(Flags.FLAG_BOUNCER_UI_REVAMP)
     fun brightnessMirror_hidesShadeBlur() {
         // Brightness mirror is fully visible
         `when`(brightnessSpring.ratio).thenReturn(1f)
@@ -427,6 +449,23 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_BOUNCER_UI_REVAMP)
+    fun brightnessMirror_hidesShadeBlur_withWindowBlurFlag() {
+        // Brightness mirror is fully visible
+        `when`(brightnessSpring.ratio).thenReturn(1f)
+        // And shade is blurred
+        notificationShadeDepthController.onPanelExpansionChanged(
+            ShadeExpansionChangeEvent(fraction = 1f, expanded = true, tracking = false)
+        )
+        `when`(shadeAnimation.radius).thenReturn(maxBlur.toFloat())
+
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(notificationShadeWindowController).setBackgroundBlurRadius(eq(0))
+        verify(wallpaperController).setNotificationShadeZoom(eq(1f))
+        verify(windowRootViewBlurInteractor).requestBlurForShade(0, false)
+    }
+
+    @Test
     fun ignoreShadeBlurUntilHidden_whennNull_ignoresIfShadeHasNoBlur() {
         `when`(shadeAnimation.radius).thenReturn(0f)
         notificationShadeDepthController.blursDisabledForAppLaunch = true
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 165e943..17076b4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -16,10 +16,12 @@
 
 package com.android.systemui.statusbar.chips.notification.ui.viewmodel
 
+import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.view.View
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -71,6 +73,7 @@
     }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_noNotifs_empty() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -81,6 +84,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_notifMissingStatusBarChipIconView_empty() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -99,6 +103,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_onePromotedNotif_statusBarIconViewMatches() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -122,6 +127,7 @@
 
     @Test
     @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_onePromotedNotif_connectedDisplaysFlagEnabled_statusBarIconMatches() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -145,6 +151,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_onePromotedNotif_colorMatches() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -175,6 +182,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_onlyForPromotedNotifs() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -208,6 +216,7 @@
 
     @Test
     @EnableFlags(StatusBarConnectedDisplays.FLAG_NAME)
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_connectedDisplaysFlagEnabled_onlyForPromotedNotifs() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -242,6 +251,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_hasShortCriticalText_usesTextInsteadOfTime() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -272,6 +282,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_noTime_isIconOnly() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -294,6 +305,67 @@
         }
 
     @Test
+    @EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+    fun chips_basicTime_timeHiddenIfAutomaticallyPromoted() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.chips)
+
+            val promotedContentBuilder =
+                PromotedNotificationContentModel.Builder("notif").apply {
+                    this.wasPromotedAutomatically = true
+                    this.time =
+                        PromotedNotificationContentModel.When(
+                            time = 6543L,
+                            mode = PromotedNotificationContentModel.When.Mode.BasicTime,
+                        )
+                }
+            setNotifs(
+                listOf(
+                    activeNotificationModel(
+                        key = "notif",
+                        statusBarChipIcon = mock<StatusBarIconView>(),
+                        promotedContent = promotedContentBuilder.build(),
+                    )
+                )
+            )
+
+            assertThat(latest).hasSize(1)
+            assertThat(latest!![0])
+                .isInstanceOf(OngoingActivityChipModel.Shown.IconOnly::class.java)
+        }
+
+    @Test
+    @EnableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
+    fun chips_basicTime_timeShownIfNotAutomaticallyPromoted() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.chips)
+
+            val promotedContentBuilder =
+                PromotedNotificationContentModel.Builder("notif").apply {
+                    this.wasPromotedAutomatically = false
+                    this.time =
+                        PromotedNotificationContentModel.When(
+                            time = 6543L,
+                            mode = PromotedNotificationContentModel.When.Mode.BasicTime,
+                        )
+                }
+            setNotifs(
+                listOf(
+                    activeNotificationModel(
+                        key = "notif",
+                        statusBarChipIcon = mock<StatusBarIconView>(),
+                        promotedContent = promotedContentBuilder.build(),
+                    )
+                )
+            )
+
+            assertThat(latest).hasSize(1)
+            assertThat(latest!![0])
+                .isInstanceOf(OngoingActivityChipModel.Shown.ShortTimeDelta::class.java)
+        }
+
+    @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_basicTime_isShortTimeDelta() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -322,6 +394,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_countUpTime_isTimer() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -349,6 +422,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_countDownTime_isTimer() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -376,6 +450,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_noHeadsUp_showsTime() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -407,6 +482,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_hasHeadsUpByUser_onlyShowsIcon() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
@@ -442,6 +518,7 @@
         }
 
     @Test
+    @DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
     fun chips_clickingChipNotifiesInteractor() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.chips)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
index 5fbdfbf..0c992e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipBackgroundContainerTest.kt
@@ -40,7 +40,7 @@
         allowTestableLooperAsMainThread()
         TestableLooper.get(this).runWithLooper {
             val chipView =
-                LayoutInflater.from(context).inflate(R.layout.ongoing_activity_chip, null)
+                LayoutInflater.from(context).inflate(R.layout.ongoing_activity_chip_primary, null)
             underTest = chipView.requireViewById(R.id.ongoing_activity_chip_background)
         }
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
index 6f771175..9483f6d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipChronometerTest.kt
@@ -48,7 +48,7 @@
         allowTestableLooperAsMainThread()
         TestableLooper.get(this).runWithLooper {
             val chipView =
-                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
             textView = chipView.findViewById(R.id.ongoing_activity_chip_time)!!
             measureTextView()
             calculateDoesNotFixText()
@@ -161,7 +161,7 @@
     private fun measureTextView() {
         textView.measure(
             View.MeasureSpec.makeMeasureSpec(TEXT_VIEW_MAX_WIDTH, View.MeasureSpec.AT_MOST),
-            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
         )
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt
new file mode 100644
index 0000000..d727089
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.view
+
+import android.view.View
+import android.widget.TextView
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.res.R
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import org.junit.Before
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ChipTextTruncationHelperTest : SysuiTestCase() {
+
+    val underTest by lazy { ChipTextTruncationHelper(TextView(context)) }
+
+    @Before
+    fun setUp() {
+        mContext.getOrCreateTestableResources().apply {
+            this.addOverride(R.dimen.ongoing_activity_chip_max_text_width, MAX_WIDTH)
+        }
+    }
+
+    @Test
+    fun shouldShowText_desiredLessThanMax_true() {
+        val result =
+            underTest.shouldShowText(
+                desiredTextWidthPx = MAX_WIDTH / 2,
+                widthMeasureSpec = UNLIMITED_WIDTH_SPEC,
+            )
+
+        assertThat(result).isTrue()
+    }
+
+    @Test
+    fun shouldShowText_desiredSlightlyLargerThanMax_true() {
+        val result =
+            underTest.shouldShowText(
+                desiredTextWidthPx = (MAX_WIDTH * 1.1).toInt(),
+                widthMeasureSpec = UNLIMITED_WIDTH_SPEC,
+            )
+
+        assertThat(result).isTrue()
+    }
+
+    @Test
+    fun shouldShowText_desiredMoreThanTwiceMax_false() {
+        val result =
+            underTest.shouldShowText(
+                desiredTextWidthPx = (MAX_WIDTH * 2.2).toInt(),
+                widthMeasureSpec = UNLIMITED_WIDTH_SPEC,
+            )
+
+        assertThat(result).isFalse()
+    }
+
+    @Test
+    fun shouldShowText_widthSpecLessThanMax_usesWidthSpec() {
+        val smallerWidthSpec =
+            SysuiMeasureSpec(
+                View.MeasureSpec.makeMeasureSpec(MAX_WIDTH / 2, View.MeasureSpec.AT_MOST)
+            )
+
+        // WHEN desired is more than twice the smallerWidthSpec
+        val desiredWidth = (MAX_WIDTH * 1.1).toInt()
+
+        val result =
+            underTest.shouldShowText(
+                desiredTextWidthPx = desiredWidth,
+                widthMeasureSpec = smallerWidthSpec,
+            )
+
+        // THEN returns false because smallerWidthSpec is used as the requirement
+        assertThat(result).isFalse()
+    }
+
+    @Test
+    fun shouldShowText_maxLessThanWidthSpec_usesMax() {
+        val largerWidthSpec =
+            SysuiMeasureSpec(
+                View.MeasureSpec.makeMeasureSpec(MAX_WIDTH * 3, View.MeasureSpec.AT_MOST)
+            )
+
+        // WHEN desired is more than twice the max
+        val desiredWidth = (MAX_WIDTH * 2.2).toInt()
+
+        val result =
+            underTest.shouldShowText(
+                desiredTextWidthPx = desiredWidth,
+                widthMeasureSpec = largerWidthSpec,
+            )
+
+        // THEN returns false because the max is used as the requirement
+        assertThat(result).isFalse()
+    }
+
+    companion object {
+        private const val MAX_WIDTH = 200
+        private val UNLIMITED_WIDTH_SPEC =
+            SysuiMeasureSpec(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
index 1a7c8a3..43bd7cf0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/commandline/ParseableCommandTest.kt
@@ -48,12 +48,14 @@
         val mySubCommand =
             object : ParseableCommand("subCommand") {
                 val flag by flag("flag")
+
                 override fun execute(pw: PrintWriter) {}
             }
 
         val mySubCommand2 =
             object : ParseableCommand("subCommand2") {
                 val flag by flag("flag")
+
                 override fun execute(pw: PrintWriter) {}
             }
 
@@ -141,6 +143,7 @@
         val cmd =
             object : ParseableCommand("test-command") {
                 val flag by flag("flag")
+
                 override fun execute(pw: PrintWriter) {}
             }
 
@@ -162,6 +165,7 @@
                 var onParseFailedCalled = false
 
                 override fun execute(pw: PrintWriter) {}
+
                 override fun onParseFailed(error: ArgParseError) {
                     onParseFailedCalled = true
                 }
@@ -204,11 +208,7 @@
         val cmd =
             object : ParseableCommand(name) {
                 val singleRequiredParam: String by
-                    param(
-                            longName = "param1",
-                            shortName = "p",
-                            valueParser = Type.String,
-                        )
+                    param(longName = "param1", shortName = "p", valueParser = Type.String)
                         .required()
 
                 override fun execute(pw: PrintWriter) {}
@@ -253,6 +253,7 @@
         val cmd =
             object : ParseableCommand(name) {
                 val subCmd by subCommand(subCmd)
+
                 override fun execute(pw: PrintWriter) {}
             }
 
@@ -293,18 +294,72 @@
         assertThat(myCommand.subCommand?.param1).isEqualTo("arg2")
     }
 
-    class MyCommand(
-        private val onExecute: ((MyCommand) -> Unit)? = null,
-    ) : ParseableCommand(name) {
+    @Test
+    fun commandWithSubCommand_allOptional_nothingPassed_execCalled() {
+        // GIVEN single sub command
+        val subName = "sub-command"
+        val subCmd =
+            object : ParseableCommand(subName) {
+                var execd = false
+
+                override fun execute(pw: PrintWriter) {
+                    execd = true
+                }
+            }
+
+        // GIVEN command wrapping the optional subcommand
+        val cmd =
+            object : ParseableCommand(name) {
+                val sub: ParseableCommand? by subCommand(subCmd)
+                var execCalled = false
+
+                override fun execute(pw: PrintWriter) {
+                    execCalled = true
+                }
+            }
+
+        // WHEN the base command is sent (i.e., sub-command is missing
+        cmd.execute(pw, listOf())
+        // THEN exec is still called, since this is a valid command
+        assertThat(cmd.execCalled).isTrue()
+    }
+
+    @Test
+    fun commandWithSubCommand_required_nothingPassed_execNotCalled() {
+        // GIVEN single sub command
+        val subName = "sub-command"
+        val subCmd =
+            object : ParseableCommand(subName) {
+                var execd = false
+
+                override fun execute(pw: PrintWriter) {
+                    execd = true
+                }
+            }
+
+        // GIVEN command wrapping the required subcommand
+        val cmd =
+            object : ParseableCommand(name) {
+                val sub: ParseableCommand? by subCommand(subCmd).required()
+                var execCalled = false
+
+                override fun execute(pw: PrintWriter) {
+                    execCalled = true
+                }
+            }
+
+        // WHEN the base command is sent (i.e., sub-command is missing
+        cmd.execute(pw, listOf())
+        // THEN exec is not called, since the subcommand is required
+        assertThat(cmd.execCalled).isFalse()
+    }
+
+    class MyCommand(private val onExecute: ((MyCommand) -> Unit)? = null) : ParseableCommand(name) {
 
         val flag1 by flag(shortName = "f", longName = "flag1", description = "flag 1 for test")
         val flag2 by flag(shortName = "g", longName = "flag2", description = "flag 2 for test")
         val singleParam: String? by
-            param(
-                shortName = "a",
-                longName = "arg1",
-                valueParser = Type.String,
-            )
+            param(shortName = "a", longName = "arg1", valueParser = Type.String)
 
         override fun execute(pw: PrintWriter) {
             onExecute?.invoke(this)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorTest.kt
new file mode 100644
index 0000000..dd81b75
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.featurepods.media.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
+import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class MediaControlChipInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
+    private val underTest = kosmos.mediaControlChipInteractor
+
+    @Test
+    fun mediaControlModel_noActiveMedia_null() =
+        kosmos.runTest {
+            val model by collectLastValue(underTest.mediaControlModel)
+
+            assertThat(model).isNull()
+        }
+
+    @Test
+    fun mediaControlModel_activeMedia_notNull() =
+        kosmos.runTest {
+            val model by collectLastValue(underTest.mediaControlModel)
+
+            val userMedia = MediaData(active = true)
+            val instanceId = userMedia.instanceId
+
+            mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+
+            assertThat(model).isNotNull()
+        }
+
+    @Test
+    fun mediaControlModel_mediaRemoved_null() =
+        kosmos.runTest {
+            val model by collectLastValue(underTest.mediaControlModel)
+
+            val userMedia = MediaData(active = true)
+            val instanceId = userMedia.instanceId
+
+            mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+
+            assertThat(model).isNotNull()
+
+            assertThat(mediaFilterRepository.removeSelectedUserMediaEntry(instanceId, userMedia))
+                .isTrue()
+            mediaFilterRepository.addMediaDataLoadingState(
+                MediaDataLoadingModel.Removed(instanceId)
+            )
+
+            assertThat(model).isNull()
+        }
+
+    @Test
+    fun mediaControlModel_songNameChanged_emitsUpdatedModel() =
+        kosmos.runTest {
+            val model by collectLastValue(underTest.mediaControlModel)
+
+            val initialSongName = "Initial Song"
+            val newSongName = "New Song"
+            val userMedia = MediaData(active = true, song = initialSongName)
+            val instanceId = userMedia.instanceId
+
+            mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
+            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))
+
+            assertThat(model).isNotNull()
+            assertThat(model?.songName).isEqualTo(initialSongName)
+
+            val updatedUserMedia = userMedia.copy(song = newSongName)
+            mediaFilterRepository.addSelectedUserMediaEntry(updatedUserMedia)
+
+            assertThat(model?.songName).isEqualTo(newSongName)
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
index a5206f5..1591208 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -84,91 +84,50 @@
 
     @Test
     fun updateDozeAmountWillThrottleFractionalInputUpdates() {
-        logger.logUpdateDozeAmount(0f, 0f, null, 0f, StatusBarState.SHADE, changed = false)
+        logger.logUpdateDozeAmount(0f, null, 0f, StatusBarState.SHADE, changed = false)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.1f, 0f, null, 0.1f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.1f, null, 0.1f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.2f, 0f, null, 0.2f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.3f, 0f, null, 0.3f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.4f, 0f, null, 0.4f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.5f, 0f, null, 0.5f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.2f, null, 0.2f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.3f, null, 0.3f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.4f, null, 0.4f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, null, 0.5f, StatusBarState.SHADE, changed = true)
         verifyDidLog(0)
-        logger.logUpdateDozeAmount(1f, 0f, null, 1f, StatusBarState.SHADE, changed = true)
-        verifyDidLog(1)
-    }
-
-    @Test
-    fun updateDozeAmountWillThrottleFractionalDelayUpdates() {
-        logger.logUpdateDozeAmount(0f, 0f, null, 0f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(0f, 0.1f, null, 0.1f, StatusBarState.SHADE, changed = true)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(0f, 0.2f, null, 0.2f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0f, 0.3f, null, 0.3f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0f, 0.4f, null, 0.4f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0f, 0.5f, null, 0.5f, StatusBarState.SHADE, changed = true)
-        verifyDidLog(0)
-        logger.logUpdateDozeAmount(0f, 1f, null, 1f, StatusBarState.SHADE, changed = true)
-        verifyDidLog(1)
-    }
-
-    @Test
-    fun updateDozeAmountWillIncludeFractionalUpdatesWhenOtherInputChangesFractionality() {
-        logger.logUpdateDozeAmount(0.0f, 1.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.1f, 1.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.2f, 1.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(0.3f, 1.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(0.4f, 1.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(0)
-        logger.logUpdateDozeAmount(0.5f, 0.9f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.6f, 0.8f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(0.8f, 0.6f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(0.9f, 0.5f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(0)
-        logger.logUpdateDozeAmount(1.0f, 0.4f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(1)
-        logger.logUpdateDozeAmount(1.0f, 0.3f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(1.0f, 0.2f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        logger.logUpdateDozeAmount(1.0f, 0.1f, 1f, 1f, StatusBarState.SHADE, changed = false)
-        verifyDidLog(0)
-        logger.logUpdateDozeAmount(1.0f, 0.0f, 1f, 1f, StatusBarState.SHADE, changed = false)
+        logger.logUpdateDozeAmount(1f, null, 1f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
     }
 
     @Test
     fun updateDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
-        logger.logUpdateDozeAmount(0f, 0f, null, 0f, StatusBarState.SHADE, changed = false)
+        logger.logUpdateDozeAmount(0f, null, 0f, StatusBarState.SHADE, changed = false)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.1f, 0f, null, 0.1f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.1f, null, 0.1f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.2f, 0f, null, 0.2f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.3f, 0f, null, 0.3f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.4f, 0f, null, 0.4f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.5f, 0f, null, 0.5f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.2f, null, 0.2f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.3f, null, 0.3f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.4f, null, 0.4f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, null, 0.5f, StatusBarState.SHADE, changed = true)
         verifyDidLog(0)
-        logger.logUpdateDozeAmount(0.5f, 0f, null, 0.5f, StatusBarState.KEYGUARD, changed = false)
+        logger.logUpdateDozeAmount(0.5f, null, 0.5f, StatusBarState.KEYGUARD, changed = false)
         verifyDidLog(1)
     }
 
     @Test
     fun updateDozeAmountWillIncludeFractionalUpdatesWhenHardOverrideChanges() {
-        logger.logUpdateDozeAmount(0f, 0f, null, 0f, StatusBarState.SHADE, changed = false)
+        logger.logUpdateDozeAmount(0f, null, 0f, StatusBarState.SHADE, changed = false)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.1f, 0f, null, 0.1f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.1f, null, 0.1f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.2f, 0f, null, 0.2f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.3f, 0f, null, 0.3f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.4f, 0f, null, 0.4f, StatusBarState.SHADE, changed = true)
-        logger.logUpdateDozeAmount(0.5f, 0f, null, 0.5f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.2f, null, 0.2f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.3f, null, 0.3f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.4f, null, 0.4f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, null, 0.5f, StatusBarState.SHADE, changed = true)
         verifyDidLog(0)
-        logger.logUpdateDozeAmount(0.5f, 0f, 1f, 1f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, 1f, 1f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.5f, 0f, 0f, 0f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, 0f, 0f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
-        logger.logUpdateDozeAmount(0.5f, 0f, null, 0.5f, StatusBarState.SHADE, changed = true)
+        logger.logUpdateDozeAmount(0.5f, null, 0.5f, StatusBarState.SHADE, changed = true)
         verifyDidLog(1)
     }
 
@@ -177,6 +136,7 @@
         val tracker =
             object : LogcatEchoTracker {
                 override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+
                 override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
                     recentLogs.add(tagName to level)
                     return true
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
index 0dc01a6..3abd620 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -37,11 +37,9 @@
 import com.android.systemui.scene.data.repository.Idle
 import com.android.systemui.scene.data.repository.setSceneTransition
 import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.ShadeViewController.Companion.WAKEUP_ANIMATION_DELAY_MS
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.notification.headsup.HeadsUpManager
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_WAKEUP
 import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -61,7 +59,6 @@
 import org.mockito.kotlin.clearInvocations
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
-import org.mockito.kotlin.never
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.verifyNoMoreInteractions
 import org.mockito.kotlin.whenever
@@ -266,52 +263,6 @@
         assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
     }
 
-    private val delayedDozeDelay = WAKEUP_ANIMATION_DELAY_MS.toLong()
-    private val delayedDozeDuration = ANIMATION_DURATION_WAKEUP.toLong()
-
-    @Test
-    fun dozeAmountOutputClampsTo1WhenDelayStarts() {
-        notificationWakeUpCoordinator.setWakingUp(true, requestDelayedAnimation = true)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-
-        // verify further doze amount changes have no effect on output
-        setDozeAmount(0.5f)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-    }
-
-    @Test
-    fun verifyDozeAmountOutputTracksDelay() {
-        dozeAmountOutputClampsTo1WhenDelayStarts()
-
-        // Animator waiting the delay amount should not yet affect the output
-        animatorTestRule.advanceTimeBy(delayedDozeDelay)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-
-        // input doze amount change to 0 has no effect
-        setDozeAmount(0.0f)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-
-        // Advancing the delay to 50% will cause the 50% output
-        animatorTestRule.advanceTimeBy(delayedDozeDuration / 2)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
-
-        // Now advance delay to 100% completion; notifications become fully visible
-        animatorTestRule.advanceTimeBy(delayedDozeDuration / 2)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
-
-        // Now advance delay to 200% completion -- should not invoke anything else
-        animatorTestRule.advanceTimeBy(delayedDozeDuration)
-        verify(stackScrollerController, never()).setDozeAmount(anyFloat())
-        verify(stackScrollerController, never()).setHideAmount(anyFloat(), anyFloat())
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
-    }
-
     @Test
     fun verifyWakeUpListenerCallbacksWhenDozing() {
         // prime internal state as dozing, then add the listener
@@ -334,85 +285,6 @@
         verifyNoMoreInteractions(wakeUpListener)
     }
 
-    @Test
-    fun verifyWakeUpListenerCallbacksWhenDelayingAnimation() {
-        // prime internal state as dozing, then add the listener
-        setDozeAmount(1f)
-        notificationWakeUpCoordinator.addListener(wakeUpListener)
-
-        // setWakingUp() doesn't do anything yet
-        notificationWakeUpCoordinator.setWakingUp(true, requestDelayedAnimation = true)
-        verifyNoMoreInteractions(wakeUpListener)
-
-        // verify further doze amount changes have no effect
-        setDozeAmount(0.5f)
-        verifyNoMoreInteractions(wakeUpListener)
-
-        // advancing to just before the start time should not invoke the listener
-        animatorTestRule.advanceTimeBy(delayedDozeDelay - 1)
-        verifyNoMoreInteractions(wakeUpListener)
-
-        animatorTestRule.advanceTimeBy(1)
-        verify(wakeUpListener).onDelayedDozeAmountAnimationRunning(eq(true))
-        verifyNoMoreInteractions(wakeUpListener)
-        clearInvocations(wakeUpListener)
-
-        // input doze amount change to 0 has no effect
-        setDozeAmount(0.0f)
-        verifyNoMoreInteractions(wakeUpListener)
-
-        // Advancing the delay to 50% will cause notifications to no longer be fully hidden
-        animatorTestRule.advanceTimeBy(delayedDozeDuration / 2)
-        verify(wakeUpListener).onFullyHiddenChanged(eq(false))
-        verifyNoMoreInteractions(wakeUpListener)
-        clearInvocations(wakeUpListener)
-
-        // Now advance delay to 99.x% completion; notifications become fully visible
-        animatorTestRule.advanceTimeBy(delayedDozeDuration / 2 - 1)
-        verifyNoMoreInteractions(wakeUpListener)
-
-        // advance to 100%; animation no longer running
-        animatorTestRule.advanceTimeBy(1)
-        verify(wakeUpListener).onDelayedDozeAmountAnimationRunning(eq(false))
-        verifyNoMoreInteractions(wakeUpListener)
-        clearInvocations(wakeUpListener)
-
-        // Now advance delay to 200% completion -- should not invoke anything else
-        animatorTestRule.advanceTimeBy(delayedDozeDuration)
-        verifyNoMoreInteractions(wakeUpListener)
-    }
-
-    @Test
-    fun verifyDelayedDozeAmountCanBeOverridden() {
-        dozeAmountOutputClampsTo1WhenDelayStarts()
-
-        // input doze amount change to 0 has no effect
-        setDozeAmount(0.0f)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-
-        // Advancing the delay to 50% will cause the 50% output
-        animatorTestRule.advanceTimeBy(delayedDozeDelay + delayedDozeDuration / 2)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
-
-        // Enabling bypass and showing keyguard will override back to fully dozing/hidden
-        setBypassEnabled(true)
-        setStatusBarState(StatusBarState.KEYGUARD)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
-    }
-
-    @Test
-    fun verifyRemovingOverrideRestoresOtherwiseCalculatedDozeAmount() {
-        verifyDelayedDozeAmountCanBeOverridden()
-
-        // Disabling bypass will return back to the 50% value
-        setBypassEnabled(false)
-        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
-        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
-    }
-
     private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
         // First verify that we did in-fact receive the correct values
         verify(stackScrollerController).setDozeAmount(eased(dozeAmount))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
similarity index 72%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
index abd0a28..9227119 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorImplTest.kt
@@ -20,6 +20,7 @@
 import android.app.Notification.BigPictureStyle
 import android.app.Notification.BigTextStyle
 import android.app.Notification.CallStyle
+import android.app.Notification.FLAG_PROMOTED_ONGOING
 import android.app.Notification.MessagingStyle
 import android.app.Notification.ProgressStyle
 import android.app.Notification.ProgressStyle.Segment
@@ -34,6 +35,7 @@
 import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
 import com.android.systemui.testKosmos
@@ -43,18 +45,15 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class PromotedNotificationContentExtractorTest : SysuiTestCase() {
+class PromotedNotificationContentExtractorImplTest : SysuiTestCase() {
     private val kosmos = testKosmos()
 
-    private val provider =
-        FakePromotedNotificationsProvider().also { kosmos.promotedNotificationsProvider = it }
-
     private val underTest = kosmos.promotedNotificationContentExtractor
 
     @Test
     @DisableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun shouldNotExtract_bothFlagsDisabled() {
-        val notif = createEntry().also { provider.promotedEntries.add(it) }
+        val notif = createEntry()
         val content = extractContent(notif)
         assertThat(content).isNull()
     }
@@ -63,7 +62,7 @@
     @EnableFlags(PromotedNotificationUi.FLAG_NAME)
     @DisableFlags(StatusBarNotifChips.FLAG_NAME)
     fun shouldExtract_promotedNotificationUiFlagEnabled() {
-        val entry = createEntry().also { provider.promotedEntries.add(it) }
+        val entry = createEntry()
         val content = extractContent(entry)
         assertThat(content).isNotNull()
     }
@@ -72,7 +71,7 @@
     @EnableFlags(StatusBarNotifChips.FLAG_NAME)
     @DisableFlags(PromotedNotificationUi.FLAG_NAME)
     fun shouldExtract_statusBarNotifChipsFlagEnabled() {
-        val entry = createEntry().also { provider.promotedEntries.add(it) }
+        val entry = createEntry()
         val content = extractContent(entry)
         assertThat(content).isNotNull()
     }
@@ -80,30 +79,27 @@
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun shouldExtract_bothFlagsEnabled() {
-        val entry = createEntry().also { provider.promotedEntries.add(it) }
+        val entry = createEntry()
         val content = extractContent(entry)
         assertThat(content).isNotNull()
     }
 
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
-    fun shouldNotExtract_providerDidNotPromote() {
-        val entry = createEntry().also { provider.promotedEntries.remove(it) }
+    fun shouldNotExtract_becauseNotPromoted() {
+        val entry = createEntry(promoted = false)
         val content = extractContent(entry)
         assertThat(content).isNull()
     }
 
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
-    fun extractContent_commonFields() {
-        val entry =
-            createEntry {
-                    setSubText(TEST_SUB_TEXT)
-                    setContentTitle(TEST_CONTENT_TITLE)
-                    setContentText(TEST_CONTENT_TEXT)
-                    setShortCriticalText(TEST_SHORT_CRITICAL_TEXT)
-                }
-                .also { provider.promotedEntries.add(it) }
+    fun extractsContent_commonFields() {
+        val entry = createEntry {
+            setSubText(TEST_SUB_TEXT)
+            setContentTitle(TEST_CONTENT_TITLE)
+            setContentText(TEST_CONTENT_TEXT)
+        }
 
         val content = extractContent(entry)
 
@@ -115,11 +111,29 @@
 
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+    fun extractContent_wasPromotedAutomatically_false() {
+        val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false) }
+
+        val content = extractContent(entry)
+
+        assertThat(content!!.wasPromotedAutomatically).isFalse()
+    }
+
+    @Test
+    @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+    fun extractContent_wasPromotedAutomatically_true() {
+        val entry = createEntry { extras.putBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, true) }
+
+        val content = extractContent(entry)
+
+        assertThat(content!!.wasPromotedAutomatically).isTrue()
+    }
+
+    @Test
+    @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     @DisableFlags(android.app.Flags.FLAG_API_RICH_ONGOING)
     fun extractContent_apiFlagOff_shortCriticalTextNotExtracted() {
-        val entry =
-            createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) }
-                .also { provider.promotedEntries.add(it) }
+        val entry = createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) }
 
         val content = extractContent(entry)
 
@@ -134,9 +148,7 @@
         android.app.Flags.FLAG_API_RICH_ONGOING,
     )
     fun extractContent_apiFlagOn_shortCriticalTextExtracted() {
-        val entry =
-            createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) }
-                .also { provider.promotedEntries.add(it) }
+        val entry = createEntry { setShortCriticalText(TEST_SHORT_CRITICAL_TEXT) }
 
         val content = extractContent(entry)
 
@@ -151,7 +163,7 @@
         android.app.Flags.FLAG_API_RICH_ONGOING,
     )
     fun extractContent_noShortCriticalTextSet_textIsNull() {
-        val entry = createEntry {}.also { provider.promotedEntries.add(it) }
+        val entry = createEntry { setShortCriticalText(null) }
 
         val content = extractContent(entry)
 
@@ -161,9 +173,8 @@
 
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
-    fun extractContent_fromBigPictureStyle() {
-        val entry =
-            createEntry { setStyle(BigPictureStyle()) }.also { provider.promotedEntries.add(it) }
+    fun extractsContent_fromBigPictureStyle() {
+        val entry = createEntry { setStyle(BigPictureStyle()) }
 
         val content = extractContent(entry)
 
@@ -174,8 +185,7 @@
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun extractContent_fromBigTextStyle() {
-        val entry =
-            createEntry { setStyle(BigTextStyle()) }.also { provider.promotedEntries.add(it) }
+        val entry = createEntry { setStyle(BigTextStyle()) }
 
         val content = extractContent(entry)
 
@@ -187,11 +197,13 @@
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun extractContent_fromCallStyle() {
         val hangUpIntent =
-            PendingIntent.getBroadcast(context, 0, Intent("hangup"), PendingIntent.FLAG_IMMUTABLE)
-
-        val entry =
-            createEntry { setStyle(CallStyle.forOngoingCall(TEST_PERSON, hangUpIntent)) }
-                .also { provider.promotedEntries.add(it) }
+            PendingIntent.getBroadcast(
+                context,
+                0,
+                Intent("hangup_action"),
+                PendingIntent.FLAG_IMMUTABLE,
+            )
+        val entry = createEntry { setStyle(CallStyle.forOngoingCall(TEST_PERSON, hangUpIntent)) }
 
         val content = extractContent(entry)
 
@@ -202,11 +214,9 @@
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun extractContent_fromProgressStyle() {
-        val entry =
-            createEntry {
-                    setStyle(ProgressStyle().addProgressSegment(Segment(100)).setProgress(75))
-                }
-                .also { provider.promotedEntries.add(it) }
+        val entry = createEntry {
+            setStyle(ProgressStyle().addProgressSegment(Segment(100)).setProgress(75))
+        }
 
         val content = extractContent(entry)
 
@@ -220,13 +230,9 @@
     @Test
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun extractContent_fromIneligibleStyle() {
-        val entry =
-            createEntry {
-                    setStyle(
-                        MessagingStyle(TEST_PERSON).addMessage("message text", 0L, TEST_PERSON)
-                    )
-                }
-                .also { provider.promotedEntries.add(it) }
+        val entry = createEntry {
+            setStyle(MessagingStyle(TEST_PERSON).addMessage("message text", 0L, TEST_PERSON))
+        }
 
         val content = extractContent(entry)
 
@@ -239,8 +245,14 @@
         return underTest.extractContent(entry, recoveredBuilder)
     }
 
-    private fun createEntry(builderBlock: Notification.Builder.() -> Unit = {}): NotificationEntry {
-        val notif = Notification.Builder(context, "a").also(builderBlock).build()
+    private fun createEntry(
+        promoted: Boolean = true,
+        builderBlock: Notification.Builder.() -> Unit = {},
+    ): NotificationEntry {
+        val notif = Notification.Builder(context, "channel").also(builderBlock).build()
+        if (promoted) {
+            notif.flags = FLAG_PROMOTED_ONGOING
+        }
         return NotificationEntryBuilder().setNotification(notif).build()
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderTest.kt
deleted file mode 100644
index a9dbe63..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderTest.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.promoted
-
-import android.app.Notification
-import android.app.Notification.FLAG_PROMOTED_ONGOING
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.Test
-
-@SmallTest
-class PromotedNotificationsProviderTest : SysuiTestCase() {
-    private val kosmos = testKosmos()
-
-    private val underTest = kosmos.promotedNotificationsProvider
-
-    @Test
-    @DisableFlags(PromotedNotificationUi.FLAG_NAME)
-    fun shouldPromote_uiFlagOff_false() {
-        val entry = createNotification(FLAG_PROMOTED_ONGOING)
-
-        assertThat(underTest.shouldPromote(entry)).isFalse()
-    }
-
-    @Test
-    @EnableFlags(PromotedNotificationUi.FLAG_NAME)
-    fun shouldPromote_uiFlagOn_notifDoesNotHaveFlag_false() {
-        val entry = createNotification(flag = null)
-
-        assertThat(underTest.shouldPromote(entry)).isFalse()
-    }
-
-    @Test
-    @EnableFlags(PromotedNotificationUi.FLAG_NAME)
-    fun shouldPromote_uiFlagOn_notifHasFlag_true() {
-        val entry = createNotification(FLAG_PROMOTED_ONGOING)
-
-        assertThat(underTest.shouldPromote(entry)).isTrue()
-    }
-
-    private fun createNotification(flag: Int? = null): NotificationEntry {
-        val n = Notification.Builder(context, "a")
-        if (flag != null) {
-            n.setFlag(flag, true)
-        }
-
-        return NotificationEntryBuilder().setNotification(n.build()).build()
-    }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 6eb2764..a49a66f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -16,12 +16,18 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
 
 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;
@@ -30,14 +36,15 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
-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 static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.app.Person;
 import android.content.Context;
+import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
 import android.os.CancellationSignal;
 import android.os.Handler;
@@ -61,12 +68,13 @@
 import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips;
 import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor;
+import com.android.systemui.statusbar.notification.promoted.FakePromotedNotificationContentExtractor;
 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi;
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.notification.row.shared.LockscreenOtpRedaction;
 import com.android.systemui.statusbar.notification.row.shared.NotificationRowContentBinderRefactor;
 import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
 import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
@@ -105,7 +113,8 @@
     @Mock private NotifLayoutInflaterFactory.Provider mNotifLayoutInflaterFactoryProvider;
     @Mock private HeadsUpStyleProvider mHeadsUpStyleProvider;
     @Mock private NotifLayoutInflaterFactory mNotifLayoutInflaterFactory;
-    @Mock private PromotedNotificationContentExtractor mPromotedNotificationContentExtractor;
+    private final FakePromotedNotificationContentExtractor mPromotedNotificationContentExtractor =
+            new FakePromotedNotificationContentExtractor();
 
     private final SmartReplyStateInflater mSmartReplyStateInflater =
             new SmartReplyStateInflater() {
@@ -155,8 +164,8 @@
 
     @Test
     public void testIncreasedHeadsUpBeingUsed() {
-        BindParams params = new BindParams();
-        params.usesIncreasedHeadsUpHeight = true;
+        BindParams params = new BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true,
+                REDACTION_TYPE_NONE);
         Notification.Builder builder = spy(mBuilder);
         mNotificationInflater.inflateNotificationViews(
                 mRow.getEntry(),
@@ -166,14 +175,15 @@
                 FLAG_CONTENT_VIEW_ALL,
                 builder,
                 mContext,
+                mContext,
                 mSmartReplyStateInflater);
         verify(builder).createHeadsUpContentView(true);
     }
 
     @Test
     public void testIncreasedHeightBeingUsed() {
-        BindParams params = new BindParams();
-        params.usesIncreasedHeight = true;
+        BindParams params = new BindParams(false, /* usesIncreasedHeight */ true, false,
+                REDACTION_TYPE_NONE);
         Notification.Builder builder = spy(mBuilder);
         mNotificationInflater.inflateNotificationViews(
                 mRow.getEntry(),
@@ -183,6 +193,7 @@
                 FLAG_CONTENT_VIEW_ALL,
                 builder,
                 mContext,
+                mContext,
                 mSmartReplyStateInflater);
         verify(builder).createContentView(true);
     }
@@ -207,7 +218,7 @@
         mRow.getEntry().getSbn().getNotification().contentView
                 = new RemoteViews(mContext.getPackageName(), com.android.systemui.res.R.layout.status_bar);
         inflateAndWait(true /* expectingException */, mNotificationInflater, FLAG_CONTENT_VIEW_ALL,
-                mRow);
+                REDACTION_TYPE_NONE, mRow);
         assertTrue(mRow.getPrivateLayout().getChildCount() == 0);
         verify(mRow, times(0)).onNotificationUpdated();
     }
@@ -227,7 +238,7 @@
                 mRow.getEntry(),
                 mRow,
                 FLAG_CONTENT_VIEW_ALL,
-                new BindParams(),
+                new BindParams(false, false, false, REDACTION_TYPE_NONE),
                 false /* forceInflate */,
                 null /* callback */);
         Assert.assertNull(mRow.getEntry().getRunningTask());
@@ -287,7 +298,7 @@
         mBuilder.setCustomContentView(new RemoteViews(getContext().getPackageName(),
                 R.layout.custom_view_dark));
         RemoteViews decoratedMediaView = mBuilder.createContentView();
-        Assert.assertFalse("The decorated media style doesn't allow a view to be reapplied!",
+        assertFalse("The decorated media style doesn't allow a view to be reapplied!",
                 NotificationContentInflater.canReapplyRemoteView(mediaView, decoratedMediaView));
     }
 
@@ -385,7 +396,8 @@
         mRow.getPrivateLayout().removeAllViews();
         mRow.getEntry().getSbn().getNotification().contentView =
                 new RemoteViews(mContext.getPackageName(), R.layout.invalid_notification_height);
-        inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
+        inflateAndWait(true, mNotificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE,
+                mRow);
         assertEquals(0, mRow.getPrivateLayout().getChildCount());
         verify(mRow, times(0)).onNotificationUpdated();
     }
@@ -395,12 +407,11 @@
     public void testExtractsPromotedContent_notWhenBothFlagsDisabled() throws Exception {
         final PromotedNotificationContentModel content =
                 new PromotedNotificationContentModel.Builder("key").build();
-        when(mPromotedNotificationContentExtractor.extractContent(any(), any()))
-                .thenReturn(content);
+        mPromotedNotificationContentExtractor.resetForEntry(mRow.getEntry(), content);
 
         inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
 
-        verify(mPromotedNotificationContentExtractor, never()).extractContent(any(), any());
+        mPromotedNotificationContentExtractor.verifyZeroExtractCalls();
     }
 
     @Test
@@ -410,12 +421,11 @@
             throws Exception {
         final PromotedNotificationContentModel content =
                 new PromotedNotificationContentModel.Builder("key").build();
-        when(mPromotedNotificationContentExtractor.extractContent(any(), any()))
-                .thenReturn(content);
+        mPromotedNotificationContentExtractor.resetForEntry(mRow.getEntry(), content);
 
         inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
 
-        verify(mPromotedNotificationContentExtractor, times(1)).extractContent(any(), any());
+        mPromotedNotificationContentExtractor.verifyOneExtractCall();
         assertEquals(content, mRow.getEntry().getPromotedNotificationContentModel());
     }
 
@@ -425,12 +435,11 @@
     public void testExtractsPromotedContent_whenStatusBarNotifChipsFlagEnabled() throws Exception {
         final PromotedNotificationContentModel content =
                 new PromotedNotificationContentModel.Builder("key").build();
-        when(mPromotedNotificationContentExtractor.extractContent(any(), any()))
-                .thenReturn(content);
+        mPromotedNotificationContentExtractor.resetForEntry(mRow.getEntry(), content);
 
         inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
 
-        verify(mPromotedNotificationContentExtractor, times(1)).extractContent(any(), any());
+        mPromotedNotificationContentExtractor.verifyOneExtractCall();
         assertEquals(content, mRow.getEntry().getPromotedNotificationContentModel());
     }
 
@@ -439,36 +448,107 @@
     public void testExtractsPromotedContent_whenBothFlagsEnabled() throws Exception {
         final PromotedNotificationContentModel content =
                 new PromotedNotificationContentModel.Builder("key").build();
-        when(mPromotedNotificationContentExtractor.extractContent(any(), any()))
-                .thenReturn(content);
+        mPromotedNotificationContentExtractor.resetForEntry(mRow.getEntry(), content);
 
         inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
 
-        verify(mPromotedNotificationContentExtractor, times(1)).extractContent(any(), any());
+        mPromotedNotificationContentExtractor.verifyOneExtractCall();
         assertEquals(content, mRow.getEntry().getPromotedNotificationContentModel());
     }
 
     @Test
     @EnableFlags({PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME})
     public void testExtractsPromotedContent_null() throws Exception {
-        when(mPromotedNotificationContentExtractor.extractContent(any(), any())).thenReturn(null);
+        mPromotedNotificationContentExtractor.resetForEntry(mRow.getEntry(), null);
 
         inflateAndWait(mNotificationInflater, FLAG_CONTENT_VIEW_ALL, mRow);
 
-        verify(mPromotedNotificationContentExtractor, times(1)).extractContent(any(), any());
+        mPromotedNotificationContentExtractor.verifyOneExtractCall();
         assertNull(mRow.getEntry().getPromotedNotificationContentModel());
     }
 
+    @Test
+    @EnableFlags(LockscreenOtpRedaction.FLAG_NAME)
+    public void testSensitiveContentPublicView_messageStyle() throws Exception {
+        String displayName = "Display Name";
+        String messageText = "Message Text";
+        String contentText = "Content Text";
+        Icon personIcon = Icon.createWithResource(mContext,
+                com.android.systemui.res.R.drawable.ic_person);
+        Person testPerson = new Person.Builder()
+                .setName(displayName)
+                .setIcon(personIcon)
+                .build();
+        Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(testPerson);
+        messagingStyle.addMessage(new Notification.MessagingStyle.Message(messageText,
+                System.currentTimeMillis(), testPerson));
+        messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL);
+        messagingStyle.setShortcutIcon(personIcon);
+        Notification messageNotif = new Notification.Builder(mContext).setSmallIcon(
+                com.android.systemui.res.R.drawable.ic_person).setStyle(messagingStyle).build();
+        ExpandableNotificationRow row = mHelper.createRow(messageNotif);
+        inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC,
+                REDACTION_TYPE_SENSITIVE_CONTENT, row);
+        NotificationContentView publicView = row.getPublicLayout();
+        assertNotNull(publicView);
+        // The display name should be included, but not the content or message text
+        assertFalse(hasText(publicView, messageText));
+        assertFalse(hasText(publicView, contentText));
+        assertTrue(hasText(publicView, displayName));
+    }
+
+    @Test
+    @EnableFlags(LockscreenOtpRedaction.FLAG_NAME)
+    public void testSensitiveContentPublicView_nonMessageStyle() throws Exception {
+        String contentTitle = "Content Title";
+        String contentText = "Content Text";
+        Notification notif = new Notification.Builder(mContext).setSmallIcon(
+                com.android.systemui.res.R.drawable.ic_person)
+                .setContentTitle(contentTitle)
+                .setContentText(contentText)
+                .build();
+        ExpandableNotificationRow row = mHelper.createRow(notif);
+        inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC,
+                REDACTION_TYPE_SENSITIVE_CONTENT, row);
+        NotificationContentView publicView = row.getPublicLayout();
+        assertNotNull(publicView);
+        assertFalse(hasText(publicView, contentText));
+        assertTrue(hasText(publicView, contentTitle));
+
+        // The standard public view should not use the content title or text
+        inflateAndWait(false, mNotificationInflater, FLAG_CONTENT_VIEW_PUBLIC,
+                REDACTION_TYPE_PUBLIC, row);
+        publicView = row.getPublicLayout();
+        assertFalse(hasText(publicView, contentText));
+        assertFalse(hasText(publicView, contentTitle));
+    }
+
+    private static boolean hasText(ViewGroup parent, CharSequence text) {
+        for (int i = 0; i < parent.getChildCount(); i++) {
+            View child = parent.getChildAt(i);
+            if (child instanceof ViewGroup) {
+                if (hasText((ViewGroup) child, text)) {
+                    return true;
+                }
+            } else if (child instanceof TextView) {
+                return ((TextView) child).getText().toString().contains(text);
+            }
+        }
+        return false;
+    }
+
     private static void inflateAndWait(NotificationContentInflater inflater,
             @InflationFlag int contentToInflate,
             ExpandableNotificationRow row)
             throws Exception {
-        inflateAndWait(false /* expectingException */, inflater, contentToInflate, row);
+        inflateAndWait(false /* expectingException */, inflater, contentToInflate,
+                REDACTION_TYPE_NONE, row);
     }
 
     private static void inflateAndWait(boolean expectingException,
             NotificationContentInflater inflater,
             @InflationFlag int contentToInflate,
+            @RedactionType int redactionType,
             ExpandableNotificationRow row) throws Exception {
         CountDownLatch countDownLatch = new CountDownLatch(1);
         final ExceptionHolder exceptionHolder = new ExceptionHolder();
@@ -496,7 +576,7 @@
                 row.getEntry(),
                 row,
                 contentToInflate,
-                new BindParams(),
+                new BindParams(false, false, false, redactionType),
                 false /* forceInflate */,
                 callback /* callback */);
         assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
index 1851799..f25ba2c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImplTest.kt
@@ -18,6 +18,7 @@
 import android.app.Notification
 import android.app.Person
 import android.content.Context
+import android.graphics.drawable.Icon
 import android.os.AsyncTask
 import android.os.Build
 import android.os.CancellationSignal
@@ -34,10 +35,14 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.res.R
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_PUBLIC
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType
 import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
 import com.android.systemui.statusbar.notification.ConversationNotificationProcessor
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor
+import com.android.systemui.statusbar.notification.promoted.FakePromotedNotificationContentExtractor
 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUi
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.BindParams
@@ -45,6 +50,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationCallback
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
@@ -67,7 +73,6 @@
 import org.mockito.kotlin.any
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
-import org.mockito.kotlin.never
 import org.mockito.kotlin.spy
 import org.mockito.kotlin.times
 import org.mockito.kotlin.verify
@@ -110,7 +115,8 @@
                 return inflatedSmartReplyState
             }
         }
-    private val promotedNotificationContentExtractor: PromotedNotificationContentExtractor = mock()
+    private val promotedNotificationContentExtractor = FakePromotedNotificationContentExtractor()
+    private val conversationNotificationProcessor: ConversationNotificationProcessor = mock()
 
     @Before
     fun setUp() {
@@ -127,7 +133,7 @@
             NotificationRowContentBinderImpl(
                 cache,
                 mock(),
-                mock<ConversationNotificationProcessor>(),
+                conversationNotificationProcessor,
                 mock(),
                 smartReplyStateInflater,
                 layoutInflaterFactoryProvider,
@@ -139,14 +145,14 @@
 
     @Test
     fun testIncreasedHeadsUpBeingUsed() {
-        val params = BindParams()
-        params.usesIncreasedHeadsUpHeight = true
+        val params =
+            BindParams(false, false, /* usesIncreasedHeadsUpHeight */ true, REDACTION_TYPE_NONE)
         val builder = spy(builder)
         notificationInflater.inflateNotificationViews(
             row.entry,
             row,
             params,
-            true /* inflateSynchronously */,
+            true, /* inflateSynchronously */
             FLAG_CONTENT_VIEW_ALL,
             builder,
             mContext,
@@ -158,14 +164,13 @@
 
     @Test
     fun testIncreasedHeightBeingUsed() {
-        val params = BindParams()
-        params.usesIncreasedHeight = true
+        val params = BindParams(false, /* usesIncreasedHeight */ true, false, REDACTION_TYPE_NONE)
         val builder = spy(builder)
         notificationInflater.inflateNotificationViews(
             row.entry,
             row,
             params,
-            true /* inflateSynchronously */,
+            true, /* inflateSynchronously */
             FLAG_CONTENT_VIEW_ALL,
             builder,
             mContext,
@@ -194,15 +199,18 @@
         row.entry.sbn.notification.contentView =
             RemoteViews(mContext.packageName, R.layout.status_bar)
         inflateAndWait(
-            true /* expectingException */,
+            true, /* expectingException */
             notificationInflater,
             FLAG_CONTENT_VIEW_ALL,
+            REDACTION_TYPE_NONE,
             row,
         )
         Assert.assertTrue(row.privateLayout.childCount == 0)
         verify(row, times(0)).onNotificationUpdated()
     }
 
+    @Test fun testInflationOfSensitiveContentPublicView() {}
+
     @Test
     fun testAsyncTaskRemoved() {
         row.entry.abortTask()
@@ -218,8 +226,8 @@
             row.entry,
             row,
             FLAG_CONTENT_VIEW_ALL,
-            BindParams(),
-            false /* forceInflate */,
+            BindParams(false, false, false, REDACTION_TYPE_NONE),
+            false, /* forceInflate */
             null, /* callback */
         )
         Assert.assertNull(row.entry.runningTask)
@@ -234,7 +242,7 @@
                 packageContext = mContext,
                 remoteViews = NewRemoteViews(),
                 contentModel = NotificationContentModel(headsUpStatusBarModel),
-                extractedPromotedNotificationContentModel = null,
+                promotedContent = null,
             )
         val countDownLatch = CountDownLatch(1)
         NotificationRowContentBinderImpl.applyRemoteView(
@@ -432,7 +440,7 @@
                 mContext.packageName,
                 com.android.systemui.tests.R.layout.invalid_notification_height,
             )
-        inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
+        inflateAndWait(true, notificationInflater, FLAG_CONTENT_VIEW_ALL, REDACTION_TYPE_NONE, row)
         Assert.assertEquals(0, row.privateLayout.childCount.toLong())
         verify(row, times(0)).onNotificationUpdated()
     }
@@ -441,7 +449,13 @@
     @Test
     fun testInflatePublicSingleLineView() {
         row.publicLayout.removeAllViews()
-        inflateAndWait(false, notificationInflater, FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE, row)
+        inflateAndWait(
+            false,
+            notificationInflater,
+            FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+            REDACTION_TYPE_NONE,
+            row,
+        )
         Assert.assertNotNull(row.publicLayout.mSingleLineView)
         Assert.assertTrue(row.publicLayout.mSingleLineView is HybridNotificationView)
     }
@@ -449,12 +463,15 @@
     @Test
     fun testInflatePublicSingleLineConversationView() {
         val testPerson = Person.Builder().setName("Person").build()
+        val style = Notification.MessagingStyle(testPerson)
         val messagingBuilder =
             Notification.Builder(mContext, "no-id")
                 .setSmallIcon(R.drawable.ic_person)
                 .setContentTitle("Title")
                 .setContentText("Text")
-                .setStyle(Notification.MessagingStyle(testPerson))
+                .setStyle(style)
+        whenever(conversationNotificationProcessor.processNotification(any(), any(), any()))
+            .thenReturn(style)
 
         val messagingRow = spy(testHelper.createRow(messagingBuilder.build()))
         messagingRow.publicLayout.removeAllViews()
@@ -462,6 +479,7 @@
             false,
             notificationInflater,
             FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE,
+            REDACTION_TYPE_NONE,
             messagingRow,
         )
         Assert.assertNotNull(messagingRow.publicLayout.mSingleLineView)
@@ -475,12 +493,11 @@
     @DisableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun testExtractsPromotedContent_notWhenBothFlagsDisabled() {
         val content = PromotedNotificationContentModel.Builder("key").build()
-        whenever(promotedNotificationContentExtractor.extractContent(any(), any()))
-            .thenReturn(content)
+        promotedNotificationContentExtractor.resetForEntry(row.entry, content)
 
         inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
 
-        verify(promotedNotificationContentExtractor, never()).extractContent(any(), any())
+        promotedNotificationContentExtractor.verifyZeroExtractCalls()
     }
 
     @Test
@@ -488,12 +505,11 @@
     @DisableFlags(StatusBarNotifChips.FLAG_NAME)
     fun testExtractsPromotedContent_whenPromotedNotificationUiFlagEnabled() {
         val content = PromotedNotificationContentModel.Builder("key").build()
-        whenever(promotedNotificationContentExtractor.extractContent(any(), any()))
-            .thenReturn(content)
+        promotedNotificationContentExtractor.resetForEntry(row.entry, content)
 
         inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
 
-        verify(promotedNotificationContentExtractor, times(1)).extractContent(any(), any())
+        promotedNotificationContentExtractor.verifyOneExtractCall()
         Assert.assertEquals(content, row.entry.promotedNotificationContentModel)
     }
 
@@ -502,12 +518,11 @@
     @DisableFlags(PromotedNotificationUi.FLAG_NAME)
     fun testExtractsPromotedContent_whenStatusBarNotifChipsFlagEnabled() {
         val content = PromotedNotificationContentModel.Builder("key").build()
-        whenever(promotedNotificationContentExtractor.extractContent(any(), any()))
-            .thenReturn(content)
+        promotedNotificationContentExtractor.resetForEntry(row.entry, content)
 
         inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
 
-        verify(promotedNotificationContentExtractor, times(1)).extractContent(any(), any())
+        promotedNotificationContentExtractor.verifyOneExtractCall()
         Assert.assertEquals(content, row.entry.promotedNotificationContentModel)
     }
 
@@ -515,15 +530,99 @@
     @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
     fun testExtractsPromotedContent_whenBothFlagsEnabled() {
         val content = PromotedNotificationContentModel.Builder("key").build()
-        whenever(promotedNotificationContentExtractor.extractContent(any(), any()))
-            .thenReturn(content)
+        promotedNotificationContentExtractor.resetForEntry(row.entry, content)
 
         inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
 
-        verify(promotedNotificationContentExtractor, times(1)).extractContent(any(), any())
+        promotedNotificationContentExtractor.verifyOneExtractCall()
         Assert.assertEquals(content, row.entry.promotedNotificationContentModel)
     }
 
+    @Test
+    @EnableFlags(PromotedNotificationUi.FLAG_NAME, StatusBarNotifChips.FLAG_NAME)
+    fun testExtractsPromotedContent_null() {
+        promotedNotificationContentExtractor.resetForEntry(row.entry, null)
+
+        inflateAndWait(notificationInflater, FLAG_CONTENT_VIEW_ALL, row)
+
+        promotedNotificationContentExtractor.verifyOneExtractCall()
+        Assert.assertNull(row.entry.promotedNotificationContentModel)
+    }
+
+    @Test
+    @Throws(java.lang.Exception::class)
+    @EnableFlags(LockscreenOtpRedaction.FLAG_NAME)
+    fun testSensitiveContentPublicView_messageStyle() {
+        val displayName = "Display Name"
+        val messageText = "Message Text"
+        val contentText = "Content Text"
+        val personIcon = Icon.createWithResource(mContext, R.drawable.ic_person)
+        val testPerson = Person.Builder().setName(displayName).setIcon(personIcon).build()
+        val messagingStyle = Notification.MessagingStyle(testPerson)
+        messagingStyle.addMessage(
+            Notification.MessagingStyle.Message(messageText, System.currentTimeMillis(), testPerson)
+        )
+        messagingStyle.setConversationType(Notification.MessagingStyle.CONVERSATION_TYPE_NORMAL)
+        messagingStyle.setShortcutIcon(personIcon)
+        val messageNotif =
+            Notification.Builder(mContext)
+                .setSmallIcon(R.drawable.ic_person)
+                .setStyle(messagingStyle)
+                .build()
+        val newRow: ExpandableNotificationRow = testHelper.createRow(messageNotif)
+        inflateAndWait(
+            false,
+            notificationInflater,
+            FLAG_CONTENT_VIEW_PUBLIC,
+            REDACTION_TYPE_SENSITIVE_CONTENT,
+            newRow,
+        )
+        // The display name should be included, but not the content or message text
+        val publicView = newRow.publicLayout
+        Assert.assertNotNull(publicView)
+        Assert.assertFalse(hasText(publicView, messageText))
+        Assert.assertFalse(hasText(publicView, contentText))
+        Assert.assertTrue(hasText(publicView, displayName))
+    }
+
+    @Test
+    @Throws(java.lang.Exception::class)
+    @EnableFlags(LockscreenOtpRedaction.FLAG_NAME)
+    fun testSensitiveContentPublicView_nonMessageStyle() {
+        val contentTitle = "Content Title"
+        val contentText = "Content Text"
+        val notif =
+            Notification.Builder(mContext)
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle(contentTitle)
+                .setContentText(contentText)
+                .build()
+        val newRow: ExpandableNotificationRow = testHelper.createRow(notif)
+        inflateAndWait(
+            false,
+            notificationInflater,
+            FLAG_CONTENT_VIEW_PUBLIC,
+            REDACTION_TYPE_SENSITIVE_CONTENT,
+            newRow,
+        )
+        var publicView = newRow.publicLayout
+        Assert.assertNotNull(publicView)
+        Assert.assertFalse(hasText(publicView, contentText))
+        Assert.assertTrue(hasText(publicView, contentTitle))
+
+        // The standard public view should not use the content title or text
+        inflateAndWait(
+            false,
+            notificationInflater,
+            FLAG_CONTENT_VIEW_PUBLIC,
+            REDACTION_TYPE_PUBLIC,
+            newRow,
+        )
+        publicView = newRow.publicLayout
+        Assert.assertFalse(hasText(publicView, contentText))
+        Assert.assertFalse(hasText(publicView, contentTitle))
+    }
+
     private class ExceptionHolder {
         var exception: Exception? = null
     }
@@ -562,13 +661,20 @@
             @InflationFlag contentToInflate: Int,
             row: ExpandableNotificationRow,
         ) {
-            inflateAndWait(false /* expectingException */, inflater, contentToInflate, row)
+            inflateAndWait(
+                false /* expectingException */,
+                inflater,
+                contentToInflate,
+                REDACTION_TYPE_NONE,
+                row,
+            )
         }
 
         private fun inflateAndWait(
             expectingException: Boolean,
             inflater: NotificationRowContentBinderImpl,
             @InflationFlag contentToInflate: Int,
+            @RedactionType redactionType: Int,
             row: ExpandableNotificationRow,
         ) {
             val countDownLatch = CountDownLatch(1)
@@ -597,12 +703,26 @@
                 row.entry,
                 row,
                 contentToInflate,
-                BindParams(),
-                false /* forceInflate */,
+                BindParams(false, false, false, redactionType),
+                false, /* forceInflate */
                 callback, /* callback */
             )
             Assert.assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS))
             exceptionHolder.exception?.let { throw it }
         }
+
+        fun hasText(parent: ViewGroup, text: CharSequence): Boolean {
+            for (i in 0 until parent.childCount) {
+                val child = parent.getChildAt(i)
+                if (child is ViewGroup) {
+                    if (hasText(child, text)) {
+                        return true
+                    }
+                } else if (child is TextView) {
+                    return child.text.toString().contains(text)
+                }
+            }
+            return false
+        }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index b323ef8..b8d1875 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -81,7 +81,7 @@
 import com.android.systemui.statusbar.notification.icon.IconBuilder;
 import com.android.systemui.statusbar.notification.icon.IconManager;
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor;
+import com.android.systemui.statusbar.notification.promoted.FakePromotedNotificationContentExtractor;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpandableNotificationRowLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -201,7 +201,7 @@
                                 new MockSmartReplyInflater(),
                                 mock(NotifLayoutInflaterFactory.Provider.class),
                                 mock(HeadsUpStyleProvider.class),
-                                mock(PromotedNotificationContentExtractor.class),
+                                new FakePromotedNotificationContentExtractor(),
                                 mock(NotificationRowContentBinderLogger.class))
                         : new NotificationContentInflater(
                                 mock(NotifRemoteViewCache.class),
@@ -212,7 +212,7 @@
                                 new MockSmartReplyInflater(),
                                 mock(NotifLayoutInflaterFactory.Provider.class),
                                 mock(HeadsUpStyleProvider.class),
-                                mock(PromotedNotificationContentExtractor.class),
+                                new FakePromotedNotificationContentExtractor(),
                                 mock(NotificationRowContentBinderLogger.class));
         contentBinder.setInflateSynchronously(true);
         mBindStage = new RowContentBindStage(contentBinder,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index de40abb..c6cffa9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -952,11 +952,10 @@
     @Test
     @EnableSceneContainer
     public void onTouchEvent_stopExpandingNotification_sceneContainerEnabled() {
-        boolean touchHandled = stopExpandingNotification();
+        stopExpandingNotification();
 
-        verify(mNotificationStackScrollLayout).startOverscrollAfterExpanding();
+        verify(mExpandHelper).finishExpanding();
         verify(mNotificationStackScrollLayout, never()).dispatchDownEventToScroller(any());
-        assertTrue(touchHandled);
     }
 
     @Test
@@ -964,11 +963,11 @@
     public void onTouchEvent_stopExpandingNotification_sceneContainerDisabled() {
         stopExpandingNotification();
 
-        verify(mNotificationStackScrollLayout, never()).startOverscrollAfterExpanding();
+        verify(mExpandHelper, never()).finishExpanding();
         verify(mNotificationStackScrollLayout).dispatchDownEventToScroller(any());
     }
 
-    private boolean stopExpandingNotification() {
+    private void stopExpandingNotification() {
         when(mNotificationStackScrollLayout.getExpandHelper()).thenReturn(mExpandHelper);
         when(mNotificationStackScrollLayout.getIsExpanded()).thenReturn(true);
         when(mNotificationStackScrollLayout.getExpandedInThisMotion()).thenReturn(true);
@@ -983,13 +982,13 @@
         NotificationStackScrollLayoutController.TouchHandler touchHandler =
                 mController.getTouchHandler();
 
-        return touchHandler.onTouchEvent(MotionEvent.obtain(
-                /* downTime= */ 0,
-                /* eventTime= */ 0,
-                MotionEvent.ACTION_DOWN,
-                0,
-                0,
-                /* metaState= */ 0
+        touchHandler.onTouchEvent(MotionEvent.obtain(
+            /* downTime= */ 0,
+            /* eventTime= */ 0,
+            MotionEvent.ACTION_DOWN,
+            0,
+            0,
+            /* metaState= */ 0
         ));
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index f48fd3c..45977886 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -24,7 +24,6 @@
 import android.platform.test.flag.junit.FlagsParameterization
 import androidx.test.filters.SmallTest
 import com.android.compose.animation.scene.ObservableTransitionState
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
 import com.android.systemui.common.shared.model.NotificationContainerBounds
@@ -91,8 +90,6 @@
 
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4::class)
-// SharedNotificationContainerViewModel is only bound when FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT is on
-@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
 class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
 
     companion object {
@@ -241,7 +238,7 @@
             shadeTestUtil.setSplitShade(true)
 
             val horizontalPosition = checkNotNull(dimens).horizontalPosition
-            assertIs<HorizontalPosition.FloatAtEnd>(horizontalPosition)
+            assertIs<HorizontalPosition.FloatAtStart>(horizontalPosition)
             assertThat(horizontalPosition.width).isEqualTo(200)
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
index c3c5a48..b0b80a9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ActivityStarterImplTest.kt
@@ -18,9 +18,14 @@
 
 import android.app.PendingIntent
 import android.content.Intent
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.shared.Flags as SharedFlags
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -32,6 +37,9 @@
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
@@ -54,6 +62,62 @@
             )
     }
 
+    @EnableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @EnableSceneContainer
+    @Test
+    fun registerTransition_forwardsTheRequest() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+        val controllerFactory = mock(ActivityTransitionAnimator.ControllerFactory::class.java)
+
+        underTest.registerTransition(cookie, controllerFactory)
+
+        verify(activityStarterInternal).registerTransition(eq(cookie), eq(controllerFactory))
+    }
+
+    @DisableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun registerTransition_doesNotForwardTheRequest_whenFlaggedOff() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+        val controllerFactory = mock(ActivityTransitionAnimator.ControllerFactory::class.java)
+
+        underTest.registerTransition(cookie, controllerFactory)
+
+        verify(activityStarterInternal, never()).registerTransition(any(), any())
+    }
+
+    @EnableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @EnableSceneContainer
+    @Test
+    fun unregisterTransition_forwardsTheRequest() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+
+        underTest.unregisterTransition(cookie)
+
+        verify(activityStarterInternal).unregisterTransition(eq(cookie))
+    }
+
+    @DisableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun unregisterTransition_doesNotForwardTheRequest_whenFlaggedOff() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+
+        underTest.unregisterTransition(cookie)
+
+        verify(activityStarterInternal, never()).unregisterTransition(any())
+    }
+
     @Test
     fun postStartActivityDismissingKeyguard_pendingIntent_postsOnMain() {
         val intent = mock(PendingIntent::class.java)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
index bac79a9..5406acf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt
@@ -48,6 +48,7 @@
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.shade.data.repository.ShadeAnimationRepository
 import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractorLegacyImpl
+import com.android.systemui.shared.Flags as SharedFlags
 import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.NotificationShadeWindowController
@@ -63,6 +64,7 @@
 import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
+import org.junit.Assert.assertThrows
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -149,6 +151,63 @@
         `when`(communalSceneInteractor.isLaunchingWidget).thenReturn(MutableStateFlow(false))
     }
 
+    @EnableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun registerTransition_registers() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+        val controllerFactory = mock(ActivityTransitionAnimator.ControllerFactory::class.java)
+        `when`(controllerFactory.cookie).thenReturn(cookie)
+
+        underTest.registerTransition(cookie, controllerFactory)
+
+        verify(activityTransitionAnimator).register(eq(cookie), any())
+    }
+
+    @DisableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun registerTransition_throws_whenFlagsAreDisabled() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+        val controllerFactory = mock(ActivityTransitionAnimator.ControllerFactory::class.java)
+
+        assertThrows(IllegalStateException::class.java) {
+            underTest.registerTransition(cookie, controllerFactory)
+        }
+
+        verify(activityTransitionAnimator, never()).register(any(), any())
+    }
+
+    @EnableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun unregisterTransition_unregisters() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+
+        underTest.unregisterTransition(cookie)
+
+        verify(activityTransitionAnimator).unregister(eq(cookie))
+    }
+
+    @DisableFlags(
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY,
+        SharedFlags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED,
+    )
+    @Test
+    fun unregisterTransition_throws_whenFlagsAreDisabled() {
+        val cookie = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+
+        assertThrows(IllegalStateException::class.java) { underTest.unregisterTransition(cookie) }
+
+        verify(activityTransitionAnimator, never()).unregister(eq(cookie))
+    }
+
     @Test
     fun startActivityDismissingKeyguard_dismissShadeWhenOccluded_runAfterKeyguardGone() {
         val intent = mock(Intent::class.java)
@@ -216,7 +275,7 @@
         underTest.startPendingIntentDismissingKeyguard(
             intent = pendingIntent,
             dismissShade = true,
-            customMessage = customMessage
+            customMessage = customMessage,
         )
         mainExecutor.runAllReady()
 
@@ -296,7 +355,7 @@
                 nullable(PendingIntent.OnFinished::class.java),
                 nullable(Handler::class.java),
                 nullable(String::class.java),
-                bundleCaptor.capture()
+                bundleCaptor.capture(),
             )
         val options = ActivityOptions.fromBundle(bundleCaptor.firstValue)
         assertThat(options.getPendingIntentBackgroundActivityStartMode())
@@ -339,7 +398,7 @@
             dismissShade = true,
             animationController = controller,
             showOverLockscreen = true,
-            skipLockscreenChecks = true
+            skipLockscreenChecks = true,
         )
         mainExecutor.runAllReady()
 
@@ -373,7 +432,7 @@
             dismissShade = true,
             animationController = controller,
             showOverLockscreen = true,
-            skipLockscreenChecks = true
+            skipLockscreenChecks = true,
         )
         mainExecutor.runAllReady()
 
@@ -413,7 +472,7 @@
             dismissShade = false,
             animationController = controller,
             showOverLockscreen = true,
-            skipLockscreenChecks = false
+            skipLockscreenChecks = false,
         )
         mainExecutor.runAllReady()
 
@@ -458,7 +517,7 @@
             dismissShade = false,
             animationController = controller,
             showOverLockscreen = true,
-            skipLockscreenChecks = false
+            skipLockscreenChecks = false,
         )
         mainExecutor.runAllReady()
 
@@ -583,7 +642,7 @@
             },
             {},
             false,
-            customMessage
+            customMessage,
         )
 
         verify(centralSurfaces).awakenDreams()
@@ -602,7 +661,7 @@
             cancelAction = null,
             dismissShade = false,
             afterKeyguardGone = false,
-            deferred = false
+            deferred = false,
         )
 
         verify(centralSurfaces, times(1)).awakenDreams()
@@ -620,7 +679,7 @@
             cancelAction = null,
             dismissShade = false,
             afterKeyguardGone = false,
-            deferred = false
+            deferred = false,
         )
 
         verify(centralSurfaces, never()).awakenDreams()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 8360042..e1589b6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -219,6 +219,7 @@
 
     @Test
     fun testAppTransitionFinished_doesNotShowManagedProfileIcon() {
+        whenever(userManager.isProfile(anyInt())).thenReturn(true)
         whenever(userManager.getUserStatusBarIconResId(anyInt())).thenReturn(0 /* ID_NULL */)
         whenever(keyguardStateController.isShowing).thenReturn(false)
         statusBarPolicy.appTransitionFinished(0)
@@ -232,6 +233,7 @@
 
     @Test
     fun testAppTransitionFinished_showsManagedProfileIcon() {
+        whenever(userManager.isProfile(anyInt())).thenReturn(true)
         whenever(userManager.getUserStatusBarIconResId(anyInt())).thenReturn(100)
         whenever(keyguardStateController.isShowing).thenReturn(false)
         statusBarPolicy.appTransitionFinished(0)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.kt
index c347347..baea1a1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.kt
@@ -17,6 +17,7 @@
 
 import android.app.Notification
 import android.app.Notification.Builder
+import android.app.PendingIntent
 import android.app.StatusBarManager
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
@@ -36,11 +37,11 @@
 import com.android.systemui.plugins.activityStarter
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.settings.FakeDisplayTracker
-import com.android.systemui.shade.NotificationShadeWindowView
-import com.android.systemui.shade.ShadeViewController
 import com.android.systemui.shade.domain.interactor.panelExpansionInteractor
+import com.android.systemui.shade.notificationShadeWindowView
 import com.android.systemui.statusbar.CommandQueue
 import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.commandQueue
 import com.android.systemui.statusbar.lockscreenShadeTransitionController
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
@@ -79,40 +80,34 @@
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper
 class StatusBarNotificationPresenterTest : SysuiTestCase() {
-    private lateinit var kosmos: Kosmos
+    private val kosmos: Kosmos =
+        testKosmos().apply {
+            whenever(notificationShadeWindowView.resources).thenReturn(mContext.resources)
+            whenever(notificationStackScrollLayoutController.view).thenReturn(mock())
+            whenever(notificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(true)
+            commandQueue = CommandQueue(mContext, FakeDisplayTracker(mContext))
 
+            // override this controller with a mock, otherwise it would start some animators which
+            // are not cleaned up after these tests
+            lockscreenShadeTransitionController = mock()
+        }
+
+    // initiated by argumentCaptors later in the setup step, based on the flag states
     private var interruptSuppressor: NotificationInterruptSuppressor? = null
     private var alertsDisabledCondition: VisualInterruptionCondition? = null
     private var vrModeCondition: VisualInterruptionCondition? = null
     private var needsRedactionFilter: VisualInterruptionFilter? = null
     private var panelsDisabledCondition: VisualInterruptionCondition? = null
 
-    private val commandQueue: CommandQueue = CommandQueue(mContext, FakeDisplayTracker(mContext))
-    private val keyguardStateController: KeyguardStateController
-        get() = kosmos.keyguardStateController
-
-    private val notificationAlertsInteractor
-        get() = kosmos.notificationAlertsInteractor
-
-    private val visualInterruptionDecisionProvider
-        get() = kosmos.visualInterruptionDecisionProvider
+    private val commandQueue: CommandQueue = kosmos.commandQueue
+    private val keyguardStateController: KeyguardStateController = kosmos.keyguardStateController
+    private val notificationAlertsInteractor = kosmos.notificationAlertsInteractor
+    private val visualInterruptionDecisionProvider = kosmos.visualInterruptionDecisionProvider
 
     private lateinit var underTest: StatusBarNotificationPresenter
 
     @Before
     fun setup() {
-        kosmos =
-            testKosmos().apply {
-                whenever(notificationAlertsInteractor.areNotificationAlertsEnabled())
-                    .thenReturn(true)
-                whenever(notificationStackScrollLayoutController.expandHelperCallback)
-                    .thenReturn(mock())
-                lockscreenShadeTransitionController.setStackScroller(
-                    notificationStackScrollLayoutController
-                )
-                lockscreenShadeTransitionController.centralSurfaces = mock()
-            }
-
         underTest = createPresenter()
         if (VisualInterruptionRefactor.isEnabled) {
             verifyAndCaptureSuppressors()
@@ -162,13 +157,12 @@
     @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressHeadsUp_disabledStatusBar_refactorDisabled() {
         commandQueue.disable(
-            DEFAULT_DISPLAY,
-            StatusBarManager.DISABLE_EXPAND,
-            0,
-            false, /* animate */
+            /* displayId = */ DEFAULT_DISPLAY,
+            /* flags = */ StatusBarManager.DISABLE_EXPAND,
+            /* reason = */ 0,
+            /* animate = */ false,
         )
         TestableLooper.get(this).processAllMessages()
-
         assertWithMessage("The panel should suppress heads up while disabled")
             .that(interruptSuppressor!!.suppressAwakeHeadsUp(createNotificationEntry()))
             .isTrue()
@@ -178,13 +172,12 @@
     @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressHeadsUp_disabledStatusBar_refactorEnabled() {
         commandQueue.disable(
-            DEFAULT_DISPLAY,
-            StatusBarManager.DISABLE_EXPAND,
-            0,
-            false, /* animate */
+            /* displayId = */ DEFAULT_DISPLAY,
+            /* flags = */ StatusBarManager.DISABLE_EXPAND,
+            /* reason = */ 0,
+            /* animate = */ false,
         )
         TestableLooper.get(this).processAllMessages()
-
         assertWithMessage("The panel should suppress heads up while disabled")
             .that(panelsDisabledCondition!!.shouldSuppress())
             .isTrue()
@@ -194,13 +187,12 @@
     @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressHeadsUp_disabledNotificationShade_refactorDisabled() {
         commandQueue.disable(
-            DEFAULT_DISPLAY,
-            0,
-            StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
-            false, /* animate */
+            /* displayId = */ DEFAULT_DISPLAY,
+            /* flags = */ 0,
+            /* reason = */ StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
+            /* animate = */ false,
         )
         TestableLooper.get(this).processAllMessages()
-
         assertWithMessage(
                 "The panel should suppress interruptions while notification shade disabled"
             )
@@ -212,13 +204,12 @@
     @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressHeadsUp_disabledNotificationShade_refactorEnabled() {
         commandQueue.disable(
-            DEFAULT_DISPLAY,
-            0,
-            StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
-            false, /* animate */
+            /* displayId = */ DEFAULT_DISPLAY,
+            /* flags = */ 0,
+            /* reason = */ StatusBarManager.DISABLE2_NOTIFICATION_SHADE,
+            /* animate = */ false,
         )
         TestableLooper.get(this).processAllMessages()
-
         assertWithMessage(
                 "The panel should suppress interruptions while notification shade disabled"
             )
@@ -240,7 +231,6 @@
     fun testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorDisabled() {
         whenever(keyguardStateController.isShowing()).thenReturn(true)
         whenever(keyguardStateController.isOccluded()).thenReturn(false)
-
         assertThat(interruptSuppressor!!.suppressAwakeHeadsUp(createFsiNotificationEntry()))
             .isFalse()
     }
@@ -250,9 +240,7 @@
     fun testNoSuppressHeadsUp_FSI_nonOccludedKeyguard_refactorEnabled() {
         whenever(keyguardStateController.isShowing()).thenReturn(true)
         whenever(keyguardStateController.isOccluded()).thenReturn(false)
-
         assertThat(needsRedactionFilter!!.shouldSuppress(createFsiNotificationEntry())).isFalse()
-
         val types: Set<VisualInterruptionType> = needsRedactionFilter!!.types
         assertThat(types).contains(VisualInterruptionType.PEEK)
         assertThat(types)
@@ -263,7 +251,6 @@
     @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressInterruptions_vrMode_refactorDisabled() {
         underTest.mVrMode = true
-
         assertWithMessage("Vr mode should suppress interruptions")
             .that(interruptSuppressor!!.suppressAwakeInterruptions(createNotificationEntry()))
             .isTrue()
@@ -273,11 +260,9 @@
     @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressInterruptions_vrMode_refactorEnabled() {
         underTest.mVrMode = true
-
         assertWithMessage("Vr mode should suppress interruptions")
             .that(vrModeCondition!!.shouldSuppress())
             .isTrue()
-
         val types: Set<VisualInterruptionType> = vrModeCondition!!.types
         assertThat(types).contains(VisualInterruptionType.PEEK)
         assertThat(types).doesNotContain(VisualInterruptionType.PULSE)
@@ -288,7 +273,6 @@
     @DisableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressInterruptions_statusBarAlertsDisabled_refactorDisabled() {
         whenever(notificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false)
-
         assertWithMessage("When alerts aren't enabled, interruptions are suppressed")
             .that(interruptSuppressor!!.suppressInterruptions(createNotificationEntry()))
             .isTrue()
@@ -298,11 +282,9 @@
     @EnableFlags(VisualInterruptionRefactor.FLAG_NAME)
     fun testSuppressInterruptions_statusBarAlertsDisabled_refactorEnabled() {
         whenever(notificationAlertsInteractor.areNotificationAlertsEnabled()).thenReturn(false)
-
         assertWithMessage("When alerts aren't enabled, interruptions are suppressed")
             .that(alertsDisabledCondition!!.shouldSuppress())
             .isTrue()
-
         val types: Set<VisualInterruptionType> = alertsDisabledCondition!!.types
         assertThat(types).contains(VisualInterruptionType.PEEK)
         assertThat(types).contains(VisualInterruptionType.PULSE)
@@ -321,15 +303,16 @@
             )
 
             // When the user expands a sensitive Notification
+            val row = createRow()
             val entry =
-                createRow().entry.apply {
-                    setSensitive(/* sensitive= */ true, /* deviceSensitive= */ true)
-                }
+                row.entry.apply { setSensitive(/* sensitive= */ true, /* deviceSensitive= */ true) }
+
             underTest.onExpandClicked(entry, mock(), /* nowExpanded= */ true)
 
             // Then we open the locked shade
-            assertThat(kosmos.sysuiStatusBarStateController.state)
-                .isEqualTo(StatusBarState.SHADE_LOCKED)
+            verify(kosmos.lockscreenShadeTransitionController)
+                // Explicit parameters to avoid issues with Kotlin default arguments in Mockito
+                .goToLockedShade(row, true)
         }
 
     @Test
@@ -352,27 +335,17 @@
 
             // Then we show the bouncer
             verify(kosmos.activityStarter).dismissKeyguardThenExecute(any(), eq(null), eq(false))
-            // AND we are still on the locked shade
-            assertThat(kosmos.sysuiStatusBarStateController.state)
-                .isEqualTo(StatusBarState.SHADE_LOCKED)
         }
 
     private fun createPresenter(): StatusBarNotificationPresenter {
-        val shadeViewController: ShadeViewController = mock()
-
-        val notificationShadeWindowView: NotificationShadeWindowView = mock()
-        whenever(notificationShadeWindowView.resources).thenReturn(mContext.resources)
-        whenever(kosmos.notificationStackScrollLayoutController.view).thenReturn(mock())
-
         val initController: InitController = InitController()
-
         return StatusBarNotificationPresenter(
-                mContext,
-                shadeViewController,
+                /* context = */ mContext,
+                /* panel = */ mock(),
                 kosmos.panelExpansionInteractor,
                 /* quickSettingsController = */ mock(),
                 kosmos.headsUpManager,
-                notificationShadeWindowView,
+                kosmos.notificationShadeWindowView,
                 kosmos.activityStarter,
                 kosmos.notificationStackScrollLayoutController,
                 kosmos.dozeScrimController,
@@ -382,13 +355,13 @@
                 kosmos.notificationAlertsInteractor,
                 kosmos.lockscreenShadeTransitionController,
                 kosmos.powerInteractor,
-                commandQueue,
+                kosmos.commandQueue,
                 kosmos.notificationLockscreenUserManager,
                 kosmos.sysuiStatusBarStateController,
                 /* notifShadeEventSource = */ mock(),
                 /* notificationMediaManager = */ mock(),
                 /* notificationGutsManager = */ mock(),
-                initController,
+                /* initController = */ initController,
                 kosmos.visualInterruptionDecisionProvider,
                 kosmos.notificationRemoteInputManager,
                 /* remoteInputManagerCallback = */ mock(),
@@ -403,6 +376,7 @@
 
         val conditionCaptor = argumentCaptor<VisualInterruptionCondition>()
         verify(visualInterruptionDecisionProvider, times(3)).addCondition(conditionCaptor.capture())
+
         val conditions: List<VisualInterruptionCondition> = conditionCaptor.allValues
         alertsDisabledCondition = conditions[0]
         vrModeCondition = conditions[1]
@@ -442,8 +416,9 @@
 
     private fun createFsiNotificationEntry(): NotificationEntry {
         val notification: Notification =
-            Builder(mContext, "a").setFullScreenIntent(mock(), true).build()
-
+            Builder(mContext, "a")
+                .setFullScreenIntent(mock<PendingIntent>(), /* highPriority= */ true)
+                .build()
         return NotificationEntryBuilder()
             .setPkg("a")
             .setOpPkg("a")
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
index b560c59..1ee8005 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/SystemUIBottomSheetDialogTest.kt
@@ -20,7 +20,9 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.runTest
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
@@ -31,7 +33,6 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.runner.RunWith
@@ -43,7 +44,7 @@
 @RunWithLooper(setAsMainLooper = true)
 class SystemUIBottomSheetDialogTest : SysuiTestCase() {
 
-    private val kosmos = testKosmos()
+    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
     private val configurationController = mock<ConfigurationController>()
     private val config = mock<Configuration>()
     private val delegate = mock<DialogDelegate<Dialog>>()
@@ -67,21 +68,17 @@
 
     @Test
     fun onStart_registersConfigCallback() {
-        kosmos.testScope.runTest {
+        kosmos.runTest {
             dialog.show()
-            runCurrent()
-
             verify(configurationController).addCallback(any())
         }
     }
 
     @Test
     fun onStop_unregisterConfigCallback() {
-        kosmos.testScope.runTest {
+        kosmos.runTest {
             dialog.show()
-            runCurrent()
             dialog.dismiss()
-            runCurrent()
 
             verify(configurationController).removeCallback(any())
         }
@@ -89,14 +86,12 @@
 
     @Test
     fun onConfigurationChanged_calledInDelegate() {
-        kosmos.testScope.runTest {
+        kosmos.runTest {
             dialog.show()
-            runCurrent()
             val captor = argumentCaptor<ConfigurationController.ConfigurationListener>()
             verify(configurationController).addCallback(capture(captor))
 
             captor.value.onConfigChanged(config)
-            runCurrent()
 
             verify(delegate).onConfigurationChanged(any(), any())
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
index f76ee5e..cd3539d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaListenerTest.kt
@@ -114,7 +114,8 @@
     fun setUp() {
         allowTestableLooperAsMainThread()
         TestableLooper.get(this).runWithLooper {
-            chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+            chipView =
+                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
         }
 
         MockitoAnnotations.initMocks(this)
@@ -498,7 +499,7 @@
         lateinit var newChipView: View
         TestableLooper.get(this).runWithLooper {
             newChipView =
-                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
         }
 
         // Change the chip view associated with the controller.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
index 647b5f8..cf512cd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerViaRepoTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_STATUS_BAR_CALL_CHIP_NOTIFICATION_ICON
-import com.android.systemui.Flags.FLAG_STATUS_BAR_CHIPS_MODERNIZATION
 import com.android.systemui.Flags.FLAG_STATUS_BAR_SCREEN_SHARING_CHIPS
 import com.android.systemui.Flags.FLAG_STATUS_BAR_USE_REPOS_FOR_CALL_CHIP
 import com.android.systemui.SysuiTestCase
@@ -104,7 +103,8 @@
     fun setUp() {
         allowTestableLooperAsMainThread()
         TestableLooper.get(this).runWithLooper {
-            chipView = LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+            chipView =
+                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
         }
 
         whenever(mockStatusBarWindowControllerStore.defaultDisplay)
@@ -134,12 +134,7 @@
         testScope.runCurrent()
         reset(mockOngoingCallListener)
 
-        whenever(
-                mockIActivityManager.getUidProcessState(
-                    eq(CALL_UID),
-                    any(),
-                )
-            )
+        whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
             .thenReturn(PROC_STATE_INVISIBLE)
     }
 
@@ -225,38 +220,18 @@
 
     @Test
     fun notifRepoHasOngoingCallNotifThenScreeningNotif_listenerNotifiedTwice() {
-        setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Ongoing,
-            )
-        )
+        setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Ongoing))
 
-        setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Screening,
-            )
-        )
+        setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Screening))
 
         verify(mockOngoingCallListener, times(2)).onOngoingCallStateChanged(any())
     }
 
     @Test
     fun notifRepoHasOngoingCallNotifThenScreeningNotif_repoUpdated() {
-        setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Ongoing,
-            )
-        )
+        setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Ongoing))
 
-        setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Screening,
-            )
-        )
+        setNotifOnRepo(activeNotificationModel(key = "notif", callType = CallType.Screening))
 
         assertThat(ongoingCallRepository.ongoingCallState.value)
             .isInstanceOf(OngoingCallModel.NoCall::class.java)
@@ -289,7 +264,7 @@
 
         chipView.measure(
             View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
-            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
         )
 
         assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
@@ -309,7 +284,7 @@
 
         chipView.measure(
             View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
-            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
         )
 
         assertThat(chipView.findViewById<View>(R.id.ongoing_activity_chip_time)?.measuredWidth)
@@ -323,11 +298,7 @@
             // Re-create the notification each time so that it's considered a different object and
             // will re-trigger the whole flow.
             setNotifOnRepo(
-                activeNotificationModel(
-                    key = "notif$i",
-                    callType = CallType.Ongoing,
-                    whenTime = 44,
-                )
+                activeNotificationModel(key = "notif$i", callType = CallType.Ongoing, whenTime = 44)
             )
         }
 
@@ -337,12 +308,7 @@
     /** Regression test for b/216248574. */
     @Test
     fun repoHasCallNotif_getUidProcessStateThrowsException_noCrash() {
-        whenever(
-                mockIActivityManager.getUidProcessState(
-                    eq(CALL_UID),
-                    any(),
-                )
-            )
+        whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
             .thenThrow(SecurityException())
 
         // No assert required, just check no crash
@@ -352,14 +318,7 @@
     /** Regression test for b/216248574. */
     @Test
     fun repoHasCallNotif_registerUidObserverThrowsException_noCrash() {
-        whenever(
-                mockIActivityManager.registerUidObserver(
-                    any(),
-                    any(),
-                    any(),
-                    any(),
-                )
-            )
+        whenever(mockIActivityManager.registerUidObserver(any(), any(), any(), any()))
             .thenThrow(SecurityException())
 
         // No assert required, just check no crash
@@ -416,11 +375,7 @@
     @Test
     fun hasOngoingCall_repoHasUnrelatedNotif_returnsFalse() {
         setNotifOnRepo(
-            activeNotificationModel(
-                key = "unrelated",
-                callType = CallType.None,
-                uid = CALL_UID,
-            )
+            activeNotificationModel(key = "unrelated", callType = CallType.None, uid = CALL_UID)
         )
 
         assertThat(controller.hasOngoingCall()).isFalse()
@@ -441,20 +396,11 @@
 
     @Test
     fun hasOngoingCall_repoHasCallNotifAndCallAppNotVisible_returnsTrue() {
-        whenever(
-                mockIActivityManager.getUidProcessState(
-                    eq(CALL_UID),
-                    any(),
-                )
-            )
+        whenever(mockIActivityManager.getUidProcessState(eq(CALL_UID), any()))
             .thenReturn(PROC_STATE_INVISIBLE)
 
         setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Ongoing,
-                uid = CALL_UID,
-            )
+            activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
         )
 
         assertThat(controller.hasOngoingCall()).isTrue()
@@ -466,11 +412,7 @@
             .thenReturn(PROC_STATE_VISIBLE)
 
         setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Ongoing,
-                uid = CALL_UID,
-            )
+            activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
         )
 
         assertThat(controller.hasOngoingCall()).isFalse()
@@ -482,11 +424,7 @@
         controller.setChipView(invalidChipView)
 
         setNotifOnRepo(
-            activeNotificationModel(
-                key = "notif",
-                callType = CallType.Ongoing,
-                uid = CALL_UID,
-            )
+            activeNotificationModel(key = "notif", callType = CallType.Ongoing, uid = CALL_UID)
         )
 
         assertThat(controller.hasOngoingCall()).isFalse()
@@ -532,7 +470,7 @@
         lateinit var newChipView: View
         TestableLooper.get(this).runWithLooper {
             newChipView =
-                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip, null)
+                LayoutInflater.from(mContext).inflate(R.layout.ongoing_activity_chip_primary, null)
         }
 
         // Change the chip view associated with the controller.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index 5a77f3d..6efb9c7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -885,6 +885,20 @@
             assertThat(latest).isFalse()
         }
 
+    @Test
+    fun defaultDataSubId_tracksRepo() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.defaultDataSubId)
+
+            connectionsRepository.defaultDataSubId.value = 1
+
+            assertThat(latest).isEqualTo(1)
+
+            connectionsRepository.defaultDataSubId.value = 2
+
+            assertThat(latest).isEqualTo(2)
+        }
+
     /**
      * Convenience method for creating a pair of subscriptions to test the filteredSubscriptions
      * flow.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
deleted file mode 100644
index db24d4b..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.shared.domain.interactor
-
-import android.app.StatusBarManager.DISABLE2_NONE
-import android.app.StatusBarManager.DISABLE_CLOCK
-import android.app.StatusBarManager.DISABLE_NONE
-import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
-import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
-import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel
-import com.android.systemui.testKosmos
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.Test
-import kotlinx.coroutines.test.runTest
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class CollapsedStatusBarInteractorTest : SysuiTestCase() {
-    val kosmos = testKosmos()
-    val testScope = kosmos.testScope
-    val disableFlagsRepo = kosmos.fakeDisableFlagsRepository
-
-    val underTest = kosmos.collapsedStatusBarInteractor
-
-    @Test
-    fun visibilityViaDisableFlags_allDisabled() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
-
-            disableFlagsRepo.disableFlags.value =
-                DisableFlagsModel(
-                    DISABLE_CLOCK or DISABLE_NOTIFICATION_ICONS or DISABLE_SYSTEM_INFO,
-                    DISABLE2_NONE,
-                    animate = false,
-                )
-
-            assertThat(latest!!.isClockAllowed).isFalse()
-            assertThat(latest!!.areNotificationIconsAllowed).isFalse()
-            assertThat(latest!!.isSystemInfoAllowed).isFalse()
-        }
-
-    @Test
-    fun visibilityViaDisableFlags_allEnabled() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
-
-            disableFlagsRepo.disableFlags.value =
-                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
-
-            assertThat(latest!!.isClockAllowed).isTrue()
-            assertThat(latest!!.areNotificationIconsAllowed).isTrue()
-            assertThat(latest!!.isSystemInfoAllowed).isTrue()
-        }
-
-    @Test
-    fun visibilityViaDisableFlags_animateFalse() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
-
-            disableFlagsRepo.disableFlags.value =
-                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
-
-            assertThat(latest!!.animate).isFalse()
-        }
-
-    @Test
-    fun visibilityViaDisableFlags_animateTrue() =
-        testScope.runTest {
-            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
-
-            disableFlagsRepo.disableFlags.value =
-                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = true)
-
-            assertThat(latest!!.animate).isTrue()
-        }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorTest.kt
new file mode 100644
index 0000000..523d17a
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import android.provider.Settings
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.res.R
+import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HomeStatusBarIconBlockListInteractorTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    private val Kosmos.underTest by Kosmos.Fixture { kosmos.homeStatusBarIconBlockListInteractor }
+
+    @Test
+    fun iconBlockList_containsResources() =
+        kosmos.runTest {
+            // GIVEN a list of blocked icons
+            overrideResource(
+                R.array.config_collapsed_statusbar_icon_blocklist,
+                arrayOf("test1", "test2"),
+            )
+
+            // GIVEN the vibrate is set to show (not blocked)
+            fakeSecureSettingsRepository.setInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 1)
+
+            val latest by collectLastValue(underTest.iconBlockList)
+
+            // THEN the volume is not the blocklist
+            assertThat(latest).containsExactly("test1", "test2")
+        }
+
+    @Test
+    fun iconBlockList_checksVolumeSetting() =
+        kosmos.runTest {
+            // GIVEN a list of blocked icons
+            overrideResource(
+                R.array.config_collapsed_statusbar_icon_blocklist,
+                arrayOf("test1", "test2"),
+            )
+
+            // GIVEN the vibrate icon is set to be hidden
+            fakeSecureSettingsRepository.setInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0)
+
+            val latest by collectLastValue(underTest.iconBlockList)
+
+            // THEN the volume is in the blocklist
+            assertThat(latest).containsExactly("test1", "test2", "volume")
+        }
+
+    @Test
+    fun iconBlockList_updatesWithVolumeSetting() =
+        kosmos.runTest {
+            // GIVEN a list of blocked icons
+            overrideResource(
+                R.array.config_collapsed_statusbar_icon_blocklist,
+                arrayOf("test1", "test2"),
+            )
+
+            fakeSecureSettingsRepository.setInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0)
+
+            val latest by collectLastValue(underTest.iconBlockList)
+
+            // Initially blocked
+            assertThat(latest).containsExactly("test1", "test2", "volume")
+
+            // Setting updates
+            fakeSecureSettingsRepository.setInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 1)
+
+            // Not blocked
+            assertThat(latest).containsExactly("test1", "test2")
+
+            // Setting updates again
+            fakeSecureSettingsRepository.setInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0)
+
+            // ... blocked
+            assertThat(latest).containsExactly("test1", "test2", "volume")
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorTest.kt
new file mode 100644
index 0000000..e496375
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorTest.kt
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import android.app.StatusBarManager.DISABLE2_NONE
+import android.app.StatusBarManager.DISABLE_CLOCK
+import android.app.StatusBarManager.DISABLE_NONE
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
+import android.telephony.CarrierConfigManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
+import com.android.systemui.statusbar.disableflags.shared.model.DisableFlagsModel
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.airplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.fake
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.carrierConfigRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.configWithOverride
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fake
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
+import com.android.systemui.statusbar.pipeline.shared.connectivityConstants
+import com.android.systemui.statusbar.pipeline.shared.fake
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HomeStatusBarInteractorTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+    val disableFlagsRepo = kosmos.fakeDisableFlagsRepository
+
+    val underTest = kosmos.homeStatusBarInteractor
+
+    @Test
+    fun visibilityViaDisableFlags_allDisabled() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+            disableFlagsRepo.disableFlags.value =
+                DisableFlagsModel(
+                    DISABLE_CLOCK or DISABLE_NOTIFICATION_ICONS or DISABLE_SYSTEM_INFO,
+                    DISABLE2_NONE,
+                    animate = false,
+                )
+
+            assertThat(latest!!.isClockAllowed).isFalse()
+            assertThat(latest!!.areNotificationIconsAllowed).isFalse()
+            assertThat(latest!!.isSystemInfoAllowed).isFalse()
+        }
+
+    @Test
+    fun visibilityViaDisableFlags_allEnabled() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+            disableFlagsRepo.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
+
+            assertThat(latest!!.isClockAllowed).isTrue()
+            assertThat(latest!!.areNotificationIconsAllowed).isTrue()
+            assertThat(latest!!.isSystemInfoAllowed).isTrue()
+        }
+
+    @Test
+    fun visibilityViaDisableFlags_animateFalse() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+            disableFlagsRepo.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
+
+            assertThat(latest!!.animate).isFalse()
+        }
+
+    @Test
+    fun visibilityViaDisableFlags_animateTrue() =
+        kosmos.runTest {
+            val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+            disableFlagsRepo.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = true)
+
+            assertThat(latest!!.animate).isTrue()
+        }
+
+    @Test
+    fun shouldShowOperatorName_trueIfCarrierConfigSaysSoAndDeviceHasData() =
+        kosmos.runTest {
+            // GIVEN default data subId is 1
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+            // GIVEN Config is enabled
+            carrierConfigRepository.fake.configsById[1] =
+                SystemUiCarrierConfig(
+                    1,
+                    configWithOverride(
+                        CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL,
+                        true,
+                    ),
+                )
+
+            // GIVEN airplane mode is off
+            airplaneModeRepository.fake.isAirplaneMode.value = false
+
+            // GIVEN hasDataCapabilities is true
+            connectivityConstants.fake.hasDataCapabilities = true
+
+            val latest by collectLastValue(underTest.shouldShowOperatorName)
+
+            // THEN we should show the operator name
+            assertThat(latest).isTrue()
+        }
+
+    @Test
+    fun shouldShowOperatorName_falseNoDataCapabilities() =
+        kosmos.runTest {
+            // GIVEN default data subId is 1
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+            // GIVEN Config is enabled
+            carrierConfigRepository.fake.configsById[1] =
+                SystemUiCarrierConfig(
+                    1,
+                    configWithOverride(
+                        CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL,
+                        true,
+                    ),
+                )
+
+            // GIVEN airplane mode is off
+            airplaneModeRepository.fake.isAirplaneMode.value = true
+
+            // WHEN hasDataCapabilities is false
+            connectivityConstants.fake.hasDataCapabilities = false
+
+            val latest by collectLastValue(underTest.shouldShowOperatorName)
+
+            // THEN we should not show the operator name
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun shouldShowOperatorName_falseWhenConfigIsOff() =
+        kosmos.runTest {
+            // GIVEN default data subId is 1
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+            // GIVEN airplane mode is off
+            airplaneModeRepository.fake.isAirplaneMode.value = false
+
+            // WHEN Config is disabled
+            carrierConfigRepository.fake.configsById[1] =
+                SystemUiCarrierConfig(
+                    1,
+                    configWithOverride(
+                        CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL,
+                        false,
+                    ),
+                )
+
+            val latest by collectLastValue(underTest.shouldShowOperatorName)
+
+            // THEN we should not show the operator name
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun shouldShowOperatorName_falseIfAirplaneMode() =
+        kosmos.runTest {
+            // GIVEN default data subId is 1
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+            // GIVEN Config is enabled
+            carrierConfigRepository.fake.configsById[1] =
+                SystemUiCarrierConfig(
+                    1,
+                    configWithOverride(
+                        CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL,
+                        true,
+                    ),
+                )
+
+            // WHEN airplane mode is on
+            airplaneModeRepository.fake.isAirplaneMode.value = true
+
+            val latest by collectLastValue(underTest.shouldShowOperatorName)
+
+            // THEN we should not show the operator name
+            assertThat(latest).isFalse()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
index eef5753..0aaf89a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeHomeStatusBarViewModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,10 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
+import android.graphics.Color
+import android.graphics.Rect
 import android.view.View
+import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
 import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
 import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
@@ -24,7 +27,9 @@
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 
-class FakeHomeStatusBarViewModel : HomeStatusBarViewModel {
+class FakeHomeStatusBarViewModel(
+    override val operatorNameViewModel: StatusBarOperatorNameViewModel
+) : HomeStatusBarViewModel {
     private val areNotificationLightsOut = MutableStateFlow(false)
 
     override val isTransitioningFromLockscreenToOccluded = MutableStateFlow(false)
@@ -38,6 +43,8 @@
 
     override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
 
+    override val shouldShowOperatorNameView = MutableStateFlow(false)
+
     override val isClockVisible =
         MutableStateFlow(
             HomeStatusBarViewModel.VisibilityModel(
@@ -65,5 +72,23 @@
             )
         )
 
+    override val iconBlockList: MutableStateFlow<List<String>> = MutableStateFlow(listOf())
+
     override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> = areNotificationLightsOut
+
+    val darkRegions = mutableListOf<Rect>()
+
+    var darkIconTint = Color.BLACK
+    var lightIconTint = Color.WHITE
+
+    override fun areaTint(displayId: Int): Flow<StatusBarTintColor> =
+        MutableStateFlow(
+            StatusBarTintColor { viewBounds ->
+                if (DarkIconDispatcher.isInAreas(darkRegions, viewBounds)) {
+                    lightIconTint
+                } else {
+                    darkIconTint
+                }
+            }
+        )
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
index 5c1141b..e91875c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelImplTest.kt
@@ -22,6 +22,7 @@
 import android.app.StatusBarManager.DISABLE_NONE
 import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
 import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
+import android.graphics.Rect
 import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.view.View
@@ -45,6 +46,7 @@
 import com.android.systemui.log.assertLogsWtf
 import com.android.systemui.mediaprojection.data.model.MediaProjectionState
 import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
+import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.scene.data.repository.sceneContainerRepository
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.screenrecord.data.model.ScreenRecordModel
@@ -73,6 +75,10 @@
 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
 import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
+import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
+import com.android.systemui.statusbar.phone.data.repository.fakeDarkIconRepository
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.setHomeStatusBarIconBlockList
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.setHomeStatusBarInteractorShowOperatorName
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
 import com.android.systemui.testKosmos
 import com.google.common.truth.Truth.assertThat
@@ -496,6 +502,72 @@
         }
 
     @Test
+    fun shouldShowOperatorNameView_allowedByInteractor_allowedByDisableFlags_visible() =
+        kosmos.runTest {
+            kosmos.setHomeStatusBarInteractorShowOperatorName(true)
+
+            val latest by collectLastValue(underTest.shouldShowOperatorNameView)
+            transitionKeyguardToGone()
+
+            fakeDisableFlagsRepository.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+            assertThat(latest).isTrue()
+        }
+
+    @Test
+    fun shouldShowOperatorNameView_disAllowedByInteractor_allowedByDisableFlags_notVisible() =
+        kosmos.runTest {
+            kosmos.setHomeStatusBarInteractorShowOperatorName(false)
+
+            transitionKeyguardToGone()
+
+            fakeDisableFlagsRepository.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+            val latest by collectLastValue(underTest.shouldShowOperatorNameView)
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun shouldShowOperatorNameView_allowedByInteractor_disallowedByDisableFlags_notVisible() =
+        kosmos.runTest {
+            kosmos.setHomeStatusBarInteractorShowOperatorName(true)
+
+            val latest by collectLastValue(underTest.shouldShowOperatorNameView)
+            transitionKeyguardToGone()
+
+            fakeDisableFlagsRepository.disableFlags.value =
+                DisableFlagsModel(DISABLE_SYSTEM_INFO, DISABLE2_NONE)
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
+    fun shouldShowOperatorNameView_allowedByInteractor_hunPinned_false() =
+        kosmos.runTest {
+            kosmos.setHomeStatusBarInteractorShowOperatorName(false)
+
+            transitionKeyguardToGone()
+
+            fakeDisableFlagsRepository.disableFlags.value =
+                DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+            // there is an active HUN
+            headsUpNotificationRepository.setNotifications(
+                UnconfinedFakeHeadsUpRowRepository(
+                    key = "key",
+                    pinnedStatus = MutableStateFlow(PinnedStatus.PinnedByUser),
+                )
+            )
+
+            val latest by collectLastValue(underTest.shouldShowOperatorNameView)
+
+            assertThat(latest).isFalse()
+        }
+
+    @Test
     fun isClockVisible_allowedByDisableFlags_visible() =
         kosmos.runTest {
             val latest by collectLastValue(underTest.isClockVisible)
@@ -930,6 +1002,66 @@
             assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
         }
 
+    @Test
+    fun areaTint_viewIsInDarkBounds_getsDarkTint() =
+        kosmos.runTest {
+            val displayId = 321
+            fakeDarkIconRepository.darkState(displayId).value =
+                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)
+
+            val areaTint by collectLastValue(underTest.areaTint(displayId))
+
+            val tint = areaTint?.tint(Rect(1, 1, 3, 3))
+
+            assertThat(tint).isEqualTo(0xAABBCC)
+        }
+
+    @Test
+    fun areaTint_viewIsNotInDarkBounds_getsDefaultTint() =
+        kosmos.runTest {
+            val displayId = 321
+            fakeDarkIconRepository.darkState(displayId).value =
+                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)
+
+            val areaTint by collectLastValue(underTest.areaTint(displayId))
+
+            val tint = areaTint?.tint(Rect(6, 6, 7, 7))
+
+            assertThat(tint).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
+        }
+
+    @Test
+    fun areaTint_viewIsInDarkBounds_darkBoundsChange_viewUpdates() =
+        kosmos.runTest {
+            val displayId = 321
+            fakeDarkIconRepository.darkState(displayId).value =
+                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)
+
+            val areaTint by collectLastValue(underTest.areaTint(displayId))
+
+            var tint = areaTint?.tint(Rect(1, 1, 3, 3))
+
+            assertThat(tint).isEqualTo(0xAABBCC)
+
+            // Dark region moves 5px to the right
+            fakeDarkIconRepository.darkState(displayId).value =
+                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(5, 0, 10, 5)), 0f, 0xAABBCC)
+
+            tint = areaTint?.tint(Rect(1, 1, 3, 3))
+
+            assertThat(tint).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
+        }
+
+    @Test
+    fun iconBlockList_followsInteractor() =
+        kosmos.runTest {
+            setHomeStatusBarIconBlockList(listOf("icon1", "icon2"))
+
+            val latest by collectLastValue(underTest.iconBlockList)
+
+            assertThat(latest).containsExactly("icon1", "icon2")
+        }
+
     private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
         ActiveNotificationsStore.Builder()
             .apply { notifications.forEach(::addIndividualNotif) }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelTest.kt
new file mode 100644
index 0000000..20cc85f
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class StatusBarOperatorNameViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+    private val Kosmos.underTest by Kosmos.Fixture { kosmos.statusBarOperatorNameViewModel }
+
+    @Test
+    fun operatorName_tracksDefaultDataCarrierName() =
+        kosmos.runTest {
+            val intr1 = fakeMobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+            val intr2 = fakeMobileIconsInteractor.getMobileConnectionInteractorForSubId(2)
+            val invalidIntr = fakeMobileIconsInteractor.getMobileConnectionInteractorForSubId(-1)
+
+            // GIVEN default data subId is 1
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+
+            intr1.carrierName.value = "Test Name 1"
+            intr2.carrierName.value = "Test Name 2"
+            invalidIntr.carrierName.value = "default network name"
+
+            val latest by collectLastValue(underTest.operatorName)
+
+            assertThat(latest).isEqualTo("Test Name 1")
+
+            fakeMobileIconsInteractor.defaultDataSubId.value = 2
+
+            assertThat(latest).isEqualTo("Test Name 2")
+
+            fakeMobileIconsInteractor.defaultDataSubId.value = -1
+
+            assertThat(latest).isEqualTo("default network name")
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
index b7a3515..abfd64a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
@@ -24,11 +24,10 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.logging.UiEventLogger
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.user.UserSwitchDialogController
-import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
@@ -47,32 +46,21 @@
 @TestableLooper.RunWithLooper
 @RunWith(AndroidJUnit4::class)
 class KeyguardQsUserSwitchControllerTest : SysuiTestCase() {
-    @Mock
-    private lateinit var userSwitcherController: UserSwitcherController
+    @Mock private lateinit var userSwitcherController: UserSwitcherController
 
-    @Mock
-    private lateinit var keyguardStateController: KeyguardStateController
+    @Mock private lateinit var keyguardStateController: KeyguardStateController
 
-    @Mock
-    private lateinit var falsingManager: FalsingManager
+    @Mock private lateinit var falsingManager: FalsingManager
 
-    @Mock
-    private lateinit var configurationController: ConfigurationController
+    @Mock private lateinit var configurationController: ConfigurationController
 
-    @Mock
-    private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var dozeParameters: DozeParameters
 
-    @Mock
-    private lateinit var dozeParameters: DozeParameters
+    @Mock private lateinit var screenOffAnimationController: ScreenOffAnimationController
 
-    @Mock
-    private lateinit var screenOffAnimationController: ScreenOffAnimationController
+    @Mock private lateinit var userSwitchDialogController: UserSwitchDialogController
 
-    @Mock
-    private lateinit var userSwitchDialogController: UserSwitchDialogController
-
-    @Mock
-    private lateinit var uiEventLogger: UiEventLogger
+    @Mock private lateinit var uiEventLogger: UiEventLogger
 
     private lateinit var view: FrameLayout
     private lateinit var testableLooper: TestableLooper
@@ -83,10 +71,12 @@
         MockitoAnnotations.initMocks(this)
         testableLooper = TestableLooper.get(this)
 
-        view = LayoutInflater.from(context)
-                .inflate(R.layout.keyguard_qs_user_switch, null) as FrameLayout
+        view =
+            LayoutInflater.from(context).inflate(R.layout.keyguard_qs_user_switch, null)
+                as FrameLayout
 
-        keyguardQsUserSwitchController = KeyguardQsUserSwitchController(
+        keyguardQsUserSwitchController =
+            KeyguardQsUserSwitchController(
                 view,
                 context,
                 context.resources,
@@ -94,11 +84,11 @@
                 keyguardStateController,
                 falsingManager,
                 configurationController,
-                statusBarStateController,
                 dozeParameters,
                 screenOffAnimationController,
                 userSwitchDialogController,
-                uiEventLogger)
+                uiEventLogger,
+            )
 
         ViewUtils.attachView(view)
         testableLooper.processAllMessages()
@@ -117,7 +107,7 @@
     fun testUiEventLogged() {
         view.findViewById<View>(R.id.kg_multi_user_avatar)?.performClick()
         verify(uiEventLogger, times(1))
-                .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP)
+            .log(LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP)
     }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
deleted file mode 100644
index 9f74915..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.policy
-
-import android.content.Context
-import android.content.pm.UserInfo
-import android.graphics.Bitmap
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.util.UserIcons
-import com.android.systemui.res.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.qs.tiles.UserDetailItemView
-import com.android.systemui.user.data.source.UserRecord
-import com.android.systemui.util.mockito.whenever
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Assert.assertTrue
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.Mock
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
-    @Mock
-    private lateinit var userSwitcherController: UserSwitcherController
-    @Mock
-    private lateinit var parent: ViewGroup
-    @Mock
-    private lateinit var keyguardUserDetailItemView: KeyguardUserDetailItemView
-    @Mock
-    private lateinit var otherView: View
-    @Mock
-    private lateinit var inflatedUserDetailItemView: KeyguardUserDetailItemView
-    @Mock
-    private lateinit var layoutInflater: LayoutInflater
-    @Mock
-    private lateinit var keyguardUserSwitcherController: KeyguardUserSwitcherController
-
-    private lateinit var adapter: KeyguardUserSwitcherController.KeyguardUserAdapter
-    private lateinit var picture: Bitmap
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        whenever(userSwitcherController.isUserSwitcherEnabled).thenReturn(true)
-
-        mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, layoutInflater)
-        `when`(layoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
-                .thenReturn(inflatedUserDetailItemView)
-        adapter = KeyguardUserSwitcherController.KeyguardUserAdapter(
-                mContext,
-                mContext.resources,
-                LayoutInflater.from(mContext),
-                userSwitcherController, keyguardUserSwitcherController)
-        picture = UserIcons.convertToBitmap(mContext.getDrawable(R.drawable.ic_avatar_user))
-    }
-
-    /**
-     * Uses the KeyguardUserAdapter to create a UserDetailItemView where the convertView has an
-     * incompatible type
-     */
-    private fun createViewFromDifferentType(
-        isCurrentUser: Boolean,
-        isGuestUser: Boolean
-    ): UserDetailItemView? {
-        val user = createUserRecord(isCurrentUser, isGuestUser)
-        return adapter.createUserDetailItemView(otherView, parent, user)
-    }
-
-    /**
-     * Uses the KeyguardUserAdapter to create a UserDetailItemView where the convertView is an
-     * instance of KeyguardUserDetailItemView
-     */
-    private fun createViewFromSameType(
-        isCurrentUser: Boolean,
-        isGuestUser: Boolean
-    ): UserDetailItemView? {
-        val user = createUserRecord(isCurrentUser, isGuestUser)
-        return adapter.createUserDetailItemView(keyguardUserDetailItemView, parent, user)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_notCurrentUser_notGuestUser_oldViewIsSameType() {
-        val v: UserDetailItemView? = createViewFromSameType(
-                isCurrentUser = false, isGuestUser = false)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_notCurrentUser_guestUser_oldViewIsSameType() {
-        val v: UserDetailItemView? = createViewFromSameType(
-                isCurrentUser = false, isGuestUser = true)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsSameType() {
-        val v: UserDetailItemView? = createViewFromSameType(
-                isCurrentUser = true, isGuestUser = false)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_currentUser_guestUser_oldViewIsSameType() {
-        val v: UserDetailItemView? = createViewFromSameType(
-                isCurrentUser = true, isGuestUser = true)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_notCurrentUser_notGuestUser_oldViewIsDifferentType() {
-        val v: UserDetailItemView? = createViewFromDifferentType(
-                isCurrentUser = false, isGuestUser = false)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_notCurrentUser_guestUser_oldViewIsDifferentType() {
-        val v: UserDetailItemView? = createViewFromDifferentType(
-                isCurrentUser = false, isGuestUser = true)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsDifferentType() {
-        val v: UserDetailItemView? = createViewFromDifferentType(
-                isCurrentUser = true, isGuestUser = false)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun shouldSetOnClickListener_currentUser_guestUser_oldViewIsDifferentType() {
-        val v: UserDetailItemView? = createViewFromDifferentType(
-                isCurrentUser = true, isGuestUser = true)
-        assertNotNull(v)
-        verify(v)!!.setOnClickListener(adapter)
-    }
-
-    @Test
-    fun testCurrentUserIsAlwaysFirst() {
-        `when`(userSwitcherController.users).thenReturn(arrayListOf(
-                createUserRecord(isCurrentUser = false, isGuestUser = false),
-                createUserRecord(isCurrentUser = true, isGuestUser = false),
-                createUserRecord(isCurrentUser = false, isGuestUser = true),
-                createUserRecord(isCurrentUser = false, isGuestUser = false)
-        ))
-
-        adapter.notifyDataSetChanged()
-        assertTrue("Expected current user to be first in list", adapter.getItem(0).isCurrent)
-        assertFalse("Did not expect current user in position 1", adapter.getItem(1).isCurrent)
-        assertFalse("Did not expect current user in position 2", adapter.getItem(2).isCurrent)
-        assertTrue("Expected guest user to remain in position 2", adapter.getItem(2).isGuest)
-        assertFalse("Did not expect current user in position 3", adapter.getItem(3).isCurrent)
-    }
-
-    private fun createUserRecord(isCurrentUser: Boolean, isGuestUser: Boolean) =
-        UserRecord(
-            UserInfo(0 /* id */, "name", 0 /* flags */),
-            picture,
-            isGuestUser,
-            isCurrentUser,
-            false /* isAddUser */,
-            false /* isRestricted */,
-            true /* isSwitchToEnabled */,
-            false /* isAddSupervisedUser */
-        )
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
index 06b3b57..b2378d2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.plugins.activityStarter
 import com.android.systemui.runOnMainThreadAndWaitForIdleSync
+import com.android.systemui.shade.data.repository.shadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.phone.systemUIDialogFactory
 import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.modesDialogViewModel
@@ -78,6 +79,7 @@
                 { kosmos.modesDialogViewModel },
                 mockDialogEventLogger,
                 kosmos.mainCoroutineContext,
+                kosmos.shadeDialogContextInteractor,
             )
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 7b52dd8..5cd0846 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -501,6 +501,7 @@
     }
 
     @Test
+    @DisableFlags(com.android.systemui.shared.Flags.FLAG_NEW_CUSTOMIZATION_PICKER_UI)
     public void onWallpaperColorsChanged_changeLockWallpaper() {
         // Should ask for a new theme when wallpaper colors change
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt
new file mode 100644
index 0000000..f90e14c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModelTest.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.view.MotionEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
+import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BackGestureScreenViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val fakeConfigRepository = kosmos.fakeConfigurationRepository
+    private val viewModel = BackGestureScreenViewModel(kosmos.configurationInteractor)
+
+    @Before
+    fun before() {
+        setThresholdResource(threshold = SWIPE_DISTANCE - 1)
+        kosmos.useUnconfinedTestDispatcher()
+    }
+
+    @Test
+    fun easterEggNotTriggeredAtStart() =
+        kosmos.runTest {
+            val easterEggTriggered by collectLastValue(viewModel.easterEggTriggered)
+            assertThat(easterEggTriggered).isFalse()
+        }
+
+    @Test
+    fun emitsProgressStateWithLeftProgressAnimation() =
+        kosmos.runTest {
+            assertProgressWhileMovingFingers(
+                deltaX = -SWIPE_DISTANCE,
+                expected =
+                    InProgress(
+                        progress = 1f,
+                        progressStartMarker = "gesture to L",
+                        progressEndMarker = "end progress L",
+                    ),
+            )
+        }
+
+    @Test
+    fun emitsProgressStateWithRightProgressAnimation() =
+        kosmos.runTest {
+            assertProgressWhileMovingFingers(
+                deltaX = SWIPE_DISTANCE,
+                expected =
+                    InProgress(
+                        progress = 1f,
+                        progressStartMarker = "gesture to R",
+                        progressEndMarker = "end progress R",
+                    ),
+            )
+        }
+
+    @Test
+    fun emitsFinishedStateWithLeftSuccessAnimation() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events = ThreeFingerGesture.swipeLeft(),
+                expected = Finished(successAnimation = R.raw.trackpad_back_success_left),
+            )
+        }
+
+    @Test
+    fun emitsFinishedStateWithRightSuccessAnimation() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events = ThreeFingerGesture.swipeRight(),
+                expected = Finished(successAnimation = R.raw.trackpad_back_success_right),
+            )
+        }
+
+    @Test
+    fun gestureRecognitionTakesLatestDistanceThresholdIntoAccount() =
+        kosmos.runTest {
+            fun performBackGesture() =
+                ThreeFingerGesture.swipeLeft().forEach { viewModel.handleEvent(it) }
+            val state by collectLastValue(viewModel.gestureUiState)
+            performBackGesture()
+            assertThat(state).isInstanceOf(Finished::class.java)
+
+            setThresholdResource(SWIPE_DISTANCE + 1)
+            performBackGesture() // now swipe distance is not enough to trigger success
+
+            assertThat(state).isInstanceOf(Error::class.java)
+        }
+
+    private fun setThresholdResource(threshold: Float) {
+        fakeConfigRepository.setDimensionPixelSize(
+            R.dimen.touchpad_tutorial_gestures_distance_threshold,
+            (threshold).toInt(),
+        )
+        fakeConfigRepository.onAnyConfigurationChange()
+    }
+
+    private fun Kosmos.assertProgressWhileMovingFingers(deltaX: Float, expected: GestureUiState) {
+        assertStateAfterEvents(
+            events = ThreeFingerGesture.eventsForGestureInProgress { move(deltaX = deltaX) },
+            expected = expected,
+        )
+    }
+
+    private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
+        val state by collectLastValue(viewModel.gestureUiState)
+        events.forEach { viewModel.handleEvent(it) }
+        assertThat(state).isEqualTo(expected)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt
new file mode 100644
index 0000000..3c06352
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModelTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.content.res.mockResources
+import android.view.MotionEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
+import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
+import com.android.systemui.touchpad.tutorial.ui.gesture.Velocity
+import com.android.systemui.touchpad.ui.gesture.fakeVelocityTracker
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HomeGestureScreenViewModelTest : SysuiTestCase() {
+
+    companion object {
+        const val GESTURE_VELOCITY = 1f
+        const val LOW_VELOCITY_THRESHOLD = GESTURE_VELOCITY - 0.01f
+        const val TOO_HIGH_VELOCITY_THRESHOLD = GESTURE_VELOCITY + 0.01f
+    }
+
+    private val kosmos = testKosmos()
+    private val fakeConfigRepository = kosmos.fakeConfigurationRepository
+    private val fakeVelocityTracker = kosmos.fakeVelocityTracker
+    private val resources = kosmos.mockResources
+
+    private val viewModel =
+        HomeGestureScreenViewModel(kosmos.configurationInteractor, resources, fakeVelocityTracker)
+
+    @Before
+    fun before() {
+        setDistanceThreshold(threshold = SWIPE_DISTANCE - 1)
+        setVelocityThreshold(threshold = LOW_VELOCITY_THRESHOLD)
+        fakeVelocityTracker.setVelocity(Velocity(GESTURE_VELOCITY))
+        kosmos.useUnconfinedTestDispatcher()
+    }
+
+    @Test
+    fun easterEggNotTriggeredAtStart() =
+        kosmos.runTest {
+            val easterEggTriggered by collectLastValue(viewModel.easterEggTriggered)
+            assertThat(easterEggTriggered).isFalse()
+        }
+
+    @Test
+    fun emitsProgressStateWithAnimationMarkers() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events =
+                    ThreeFingerGesture.eventsForGestureInProgress {
+                        move(deltaY = -SWIPE_DISTANCE)
+                    },
+                expected =
+                    InProgress(
+                        progress = 1f,
+                        progressStartMarker = "drag with gesture",
+                        progressEndMarker = "release playback realtime",
+                    ),
+            )
+        }
+
+    @Test
+    fun emitsFinishedStateWithSuccessAnimation() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events = ThreeFingerGesture.swipeUp(),
+                expected = Finished(successAnimation = R.raw.trackpad_home_success),
+            )
+        }
+
+    private fun performHomeGesture() {
+        ThreeFingerGesture.swipeUp().forEach { viewModel.handleEvent(it) }
+    }
+
+    @Test
+    fun gestureRecognitionTakesLatestDistanceThresholdIntoAccount() =
+        kosmos.runTest {
+            val state by collectLastValue(viewModel.gestureUiState)
+            performHomeGesture()
+            assertThat(state).isInstanceOf(Finished::class.java)
+
+            setDistanceThreshold(SWIPE_DISTANCE + 1)
+            performHomeGesture() // now swipe distance is not enough to trigger success
+
+            assertThat(state).isInstanceOf(Error::class.java)
+        }
+
+    @Test
+    fun gestureRecognitionTakesLatestVelocityThresholdIntoAccount() =
+        kosmos.runTest {
+            val state by collectLastValue(viewModel.gestureUiState)
+            performHomeGesture()
+            assertThat(state).isInstanceOf(Finished::class.java)
+
+            setVelocityThreshold(TOO_HIGH_VELOCITY_THRESHOLD)
+            performHomeGesture()
+
+            assertThat(state).isInstanceOf(Error::class.java)
+        }
+
+    private fun setDistanceThreshold(threshold: Float) {
+        fakeConfigRepository.setDimensionPixelSize(
+            R.dimen.touchpad_tutorial_gestures_distance_threshold,
+            (threshold).toInt(),
+        )
+        fakeConfigRepository.onAnyConfigurationChange()
+    }
+
+    private fun setVelocityThreshold(threshold: Float) {
+        whenever(resources.getDimension(R.dimen.touchpad_home_gesture_velocity_threshold))
+            .thenReturn(threshold)
+        fakeConfigRepository.onAnyConfigurationChange()
+    }
+
+    private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
+        val state by collectLastValue(viewModel.gestureUiState)
+        events.forEach { viewModel.handleEvent(it) }
+        assertThat(state).isEqualTo(expected)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt
new file mode 100644
index 0000000..a2d8a8b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModelTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.content.res.mockResources
+import android.view.MotionEvent
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Error
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.MultiFingerGesture.Companion.SWIPE_DISTANCE
+import com.android.systemui.touchpad.tutorial.ui.gesture.ThreeFingerGesture
+import com.android.systemui.touchpad.tutorial.ui.gesture.Velocity
+import com.android.systemui.touchpad.ui.gesture.fakeVelocityTracker
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class RecentAppsGestureScreenViewModelTest : SysuiTestCase() {
+
+    companion object {
+        const val GESTURE_VELOCITY = 1f
+        const val VELOCITY_THRESHOLD = GESTURE_VELOCITY + 0.01f
+        const val TOO_LOW_VELOCITY_THRESHOLD = GESTURE_VELOCITY - 0.01f
+    }
+
+    private val kosmos = testKosmos()
+    private val fakeConfigRepository = kosmos.fakeConfigurationRepository
+    private val fakeVelocityTracker = kosmos.fakeVelocityTracker
+    private val resources = kosmos.mockResources
+
+    private val viewModel =
+        RecentAppsGestureScreenViewModel(
+            kosmos.configurationInteractor,
+            resources,
+            fakeVelocityTracker,
+        )
+
+    @Before
+    fun before() {
+        setDistanceThreshold(threshold = SWIPE_DISTANCE - 1)
+        setVelocityThreshold(threshold = VELOCITY_THRESHOLD)
+        fakeVelocityTracker.setVelocity(Velocity(GESTURE_VELOCITY))
+        kosmos.useUnconfinedTestDispatcher()
+    }
+
+    @Test
+    fun easterEggNotTriggeredAtStart() =
+        kosmos.runTest {
+            val easterEggTriggered by collectLastValue(viewModel.easterEggTriggered)
+            assertThat(easterEggTriggered).isFalse()
+        }
+
+    @Test
+    fun emitsProgressStateWithAnimationMarkers() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events =
+                    ThreeFingerGesture.eventsForGestureInProgress {
+                        move(deltaY = -SWIPE_DISTANCE)
+                    },
+                expected =
+                    InProgress(
+                        progress = 1f,
+                        progressStartMarker = "drag with gesture",
+                        progressEndMarker = "onPause",
+                    ),
+            )
+        }
+
+    @Test
+    fun emitsFinishedStateWithSuccessAnimation() =
+        kosmos.runTest {
+            assertStateAfterEvents(
+                events = ThreeFingerGesture.swipeUp(),
+                expected = Finished(successAnimation = R.raw.trackpad_recent_apps_success),
+            )
+        }
+
+    private fun performRecentAppsGesture() {
+        ThreeFingerGesture.swipeUp().forEach { viewModel.handleEvent(it) }
+    }
+
+    @Test
+    fun gestureRecognitionTakesLatestDistanceThresholdIntoAccount() =
+        kosmos.runTest {
+            val state by collectLastValue(viewModel.gestureUiState)
+            performRecentAppsGesture()
+            assertThat(state).isInstanceOf(Finished::class.java)
+
+            setDistanceThreshold(SWIPE_DISTANCE + 1)
+            performRecentAppsGesture() // now swipe distance is not enough to trigger success
+
+            assertThat(state).isInstanceOf(Error::class.java)
+        }
+
+    @Test
+    fun gestureRecognitionTakesLatestVelocityThresholdIntoAccount() =
+        kosmos.runTest {
+            val state by collectLastValue(viewModel.gestureUiState)
+            performRecentAppsGesture()
+            assertThat(state).isInstanceOf(Finished::class.java)
+
+            setVelocityThreshold(TOO_LOW_VELOCITY_THRESHOLD)
+            performRecentAppsGesture()
+
+            assertThat(state).isInstanceOf(Error::class.java)
+        }
+
+    private fun setDistanceThreshold(threshold: Float) {
+        whenever(
+                resources.getDimensionPixelSize(
+                    R.dimen.touchpad_tutorial_gestures_distance_threshold
+                )
+            )
+            .thenReturn(threshold.toInt())
+        fakeConfigRepository.onAnyConfigurationChange()
+    }
+
+    private fun setVelocityThreshold(threshold: Float) {
+        whenever(resources.getDimension(R.dimen.touchpad_recent_apps_gesture_velocity_threshold))
+            .thenReturn(threshold)
+        fakeConfigRepository.onAnyConfigurationChange()
+    }
+
+    private fun Kosmos.assertStateAfterEvents(events: List<MotionEvent>, expected: GestureUiState) {
+        val state by collectLastValue(viewModel.gestureUiState)
+        events.forEach { viewModel.handleEvent(it) }
+        assertThat(state).isEqualTo(expected)
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
index c29b86c..1135a5f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt
@@ -19,8 +19,6 @@
 import android.hardware.devicestate.DeviceStateManager
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener
 import android.os.PowerManager
-import android.view.ViewGroup
-import android.view.ViewTreeObserver
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.internal.util.LatencyTracker
@@ -74,10 +72,6 @@
 
     @Mock lateinit var shadeViewController: ShadeViewController
 
-    @Mock lateinit var viewGroup: ViewGroup
-
-    @Mock lateinit var viewTreeObserver: ViewTreeObserver
-
     @Mock lateinit var shadeFoldAnimator: ShadeFoldAnimator
 
     @Mock lateinit var foldTransitionInteractor: ToAodFoldTransitionInteractor
@@ -97,11 +91,8 @@
 
         deviceStates = FoldableTestUtils.findDeviceStates(context)
 
-        // TODO(b/254878364): remove this call to NPVC.getView()
         whenever(shadeViewController.shadeFoldAnimator).thenReturn(shadeFoldAnimator)
         whenever(foldTransitionInteractor.foldAnimator).thenReturn(shadeFoldAnimator)
-        whenever(shadeFoldAnimator.view).thenReturn(viewGroup)
-        whenever(viewGroup.viewTreeObserver).thenReturn(viewTreeObserver)
         whenever(wakefulnessLifecycle.lastSleepReason)
             .thenReturn(PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD)
         whenever(shadeFoldAnimator.startFoldToAodAnimation(any(), any(), any())).then {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
index d5651ec..e2f363b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
@@ -52,7 +52,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 class GuestUserInteractorTest : SysuiTestCase() {
 
     @Mock private lateinit var manager: UserManager
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractorTest.kt
index 3f995c6..87d782e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractorTest.kt
@@ -172,9 +172,9 @@
                 runCurrent()
 
                 assertThat(slidersModel!!.slider)
-                    .isEqualTo(VolumeDialogSliderType.Stream(AudioManager.STREAM_MUSIC))
+                    .isEqualTo(VolumeDialogSliderType.Stream(AudioManager.STREAM_SYSTEM))
                 assertThat(slidersModel!!.floatingSliders)
-                    .containsExactly(VolumeDialogSliderType.Stream(AudioManager.STREAM_SYSTEM))
+                    .containsExactly(VolumeDialogSliderType.Stream(AudioManager.STREAM_MUSIC))
             }
         }
     }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorTest.kt
new file mode 100644
index 0000000..bc16bec
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WindowRootViewBlurInteractorTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+
+    val underTest by lazy { kosmos.windowRootViewBlurInteractor }
+
+    @Test
+    fun bouncerBlurIsAppliedImmediately() =
+        testScope.runTest {
+            val blurRadius by collectLastValue(underTest.blurRadius)
+            val isBlurOpaque by collectLastValue(underTest.isBlurOpaque)
+
+            underTest.requestBlurForBouncer(10)
+
+            assertThat(blurRadius).isEqualTo(10)
+            assertThat(isBlurOpaque).isFalse()
+        }
+
+    @Test
+    fun shadeBlurIsNotAppliedWhenBouncerBlurIsActive() =
+        testScope.runTest {
+            kosmos.fakeKeyguardBouncerRepository.setPrimaryShow(true)
+
+            assertThat(underTest.requestBlurForShade(30, true)).isFalse()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelTest.kt
new file mode 100644
index 0000000..b97fe57
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.lifecycle.activateIn
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WindowRootViewModelTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    val testScope = kosmos.testScope
+
+    val underTest by lazy { kosmos.windowRootViewModel }
+
+    @Before
+    fun setup() {
+        underTest.activateIn(testScope)
+    }
+
+    @Test
+    fun bouncerTransitionChangesWindowBlurRadius() =
+        testScope.runTest {
+            val blurState by collectLastValue(underTest.blurState)
+            runCurrent()
+
+            kosmos.fakeBouncerTransitions.first().windowBlurRadius.value = 30.0f
+            runCurrent()
+
+            assertThat(blurState).isEqualTo(BlurState(radius = 30, isOpaque = false))
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/TestableBubbleController.java
index 4a5ebd0..aa71b84 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -25,7 +25,6 @@
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.bubbles.BubbleController;
 import com.android.wm.shell.bubbles.BubbleData;
 import com.android.wm.shell.bubbles.BubbleDataRepository;
@@ -33,6 +32,8 @@
 import com.android.wm.shell.bubbles.BubblePositioner;
 import com.android.wm.shell.bubbles.properties.BubbleProperties;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -62,7 +63,8 @@
             BubbleDataRepository dataRepository,
             IStatusBarService statusBarService,
             WindowManager windowManager,
-            WindowManagerShellWrapper windowManagerShellWrapper,
+            DisplayInsetsController displayInsetsController,
+            DisplayImeController displayImeController,
             UserManager userManager,
             LauncherApps launcherApps,
             BubbleLogger bubbleLogger,
@@ -81,8 +83,8 @@
             BubbleProperties bubbleProperties) {
         super(context, shellInit, shellCommandHandler, shellController, data, Runnable::run,
                 floatingContentCoordinator, dataRepository, statusBarService, windowManager,
-                windowManagerShellWrapper, userManager, launcherApps, bubbleLogger,
-                taskStackListener, shellTaskOrganizer, positioner, displayController,
+                displayInsetsController, displayImeController, userManager, launcherApps,
+                bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, displayController,
                 oneHandedOptional, dragAndDropController, shellMainExecutor, shellMainHandler,
                 new SyncExecutor(), taskViewTransitions, transitions,
                 syncQueue, wmService, bubbleProperties);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index abb721a..55be9f7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -16,6 +16,7 @@
 
 import android.annotation.Nullable;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -33,6 +34,22 @@
 public interface ActivityStarter {
     int VERSION = 2;
 
+    /**
+     * Registers the given {@link ActivityTransitionAnimator.ControllerFactory} for launching and
+     * closing transitions matching the {@link ActivityTransitionAnimator.TransitionCookie} and the
+     * {@link ComponentName} that it contains.
+     */
+    void registerTransition(
+            ActivityTransitionAnimator.TransitionCookie cookie,
+            ActivityTransitionAnimator.ControllerFactory controllerFactory);
+
+    /**
+     * Unregisters the {@link ActivityTransitionAnimator.ControllerFactory} previously registered
+     * containing the given {@link ActivityTransitionAnimator.TransitionCookie}. If no such
+     * registration exists, this is a no-op.
+     */
+    void unregisterTransition(ActivityTransitionAnimator.TransitionCookie cookie);
+
     void startPendingIntentDismissingKeyguard(PendingIntent intent);
 
     /**
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt
index 843afb8..a075d0d 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockFaceLayout.kt
@@ -13,7 +13,6 @@
  */
 package com.android.systemui.plugins.clocks
 
-import android.content.Context
 import android.util.DisplayMetrics
 import android.view.View
 import androidx.constraintlayout.widget.ConstraintSet
@@ -27,6 +26,8 @@
 import com.android.systemui.plugins.annotations.GeneratedImport
 import com.android.systemui.plugins.annotations.ProtectedInterface
 import com.android.systemui.plugins.annotations.ProtectedReturn
+import com.android.systemui.plugins.clocks.ContextExt.getDimen
+import com.android.systemui.plugins.clocks.ContextExt.getId
 
 /** Specifies layout information for the clock face */
 @ProtectedInterface
@@ -94,18 +95,18 @@
             constraints: ConstraintSet,
         ): ConstraintSet {
             constraints.apply {
-                val context = clockPreviewConfig.previewContext
-                val lockscreenClockViewLargeId = getId(context, "lockscreen_clock_view_large")
+                val context = clockPreviewConfig.context
+                val lockscreenClockViewLargeId = context.getId("lockscreen_clock_view_large")
                 constrainWidth(lockscreenClockViewLargeId, WRAP_CONTENT)
                 constrainHeight(lockscreenClockViewLargeId, WRAP_CONTENT)
                 constrainMaxHeight(lockscreenClockViewLargeId, 0)
 
                 val largeClockTopMargin =
                     SystemBarUtils.getStatusBarHeight(context) +
-                        getDimen(context, "small_clock_padding_top") +
-                        getDimen(context, "keyguard_smartspace_top_offset") +
-                        getDimen(context, "date_weather_view_height") +
-                        getDimen(context, "enhanced_smartspace_height")
+                        context.getDimen("small_clock_padding_top") +
+                        context.getDimen("keyguard_smartspace_top_offset") +
+                        context.getDimen("date_weather_view_height") +
+                        context.getDimen("enhanced_smartspace_height")
                 connect(lockscreenClockViewLargeId, TOP, PARENT_ID, TOP, largeClockTopMargin)
                 connect(lockscreenClockViewLargeId, START, PARENT_ID, START)
                 connect(lockscreenClockViewLargeId, END, PARENT_ID, END)
@@ -119,7 +120,7 @@
                     connect(lockscreenClockViewLargeId, BOTTOM, lockId, TOP)
                 }
                     ?: run {
-                        val bottomPaddingPx = getDimen(context, "lock_icon_margin_bottom")
+                        val bottomPaddingPx = context.getDimen("lock_icon_margin_bottom")
                         val defaultDensity =
                             DisplayMetrics.DENSITY_DEVICE_STABLE.toFloat() /
                                 DisplayMetrics.DENSITY_DEFAULT.toFloat()
@@ -134,52 +135,22 @@
                         )
                     }
 
-                val smallClockViewId = getId(context, "lockscreen_clock_view")
+                val smallClockViewId = context.getId("lockscreen_clock_view")
                 constrainWidth(smallClockViewId, WRAP_CONTENT)
-                constrainHeight(smallClockViewId, getDimen(context, "small_clock_height"))
+                constrainHeight(smallClockViewId, context.getDimen("small_clock_height"))
                 connect(
                     smallClockViewId,
                     START,
                     PARENT_ID,
                     START,
-                    getDimen(context, "clock_padding_start") +
-                        getDimen(context, "status_view_margin_horizontal"),
+                    context.getDimen("clock_padding_start") +
+                        context.getDimen("status_view_margin_horizontal"),
                 )
-                val smallClockTopMargin =
-                    getSmallClockTopPadding(
-                        clockPreviewConfig = clockPreviewConfig,
-                        SystemBarUtils.getStatusBarHeight(context),
-                    )
+
+                val smallClockTopMargin = clockPreviewConfig.getSmallClockTopPadding()
                 connect(smallClockViewId, TOP, PARENT_ID, TOP, smallClockTopMargin)
             }
             return constraints
         }
-
-        fun getId(context: Context, name: String): Int {
-            val packageName = context.packageName
-            val res = context.packageManager.getResourcesForApplication(packageName)
-            val id = res.getIdentifier(name, "id", packageName)
-            return id
-        }
-
-        fun getDimen(context: Context, name: String): Int {
-            val packageName = context.packageName
-            val res = context.resources
-            val id = res.getIdentifier(name, "dimen", packageName)
-            return if (id == 0) 0 else res.getDimensionPixelSize(id)
-        }
-
-        fun getSmallClockTopPadding(
-            clockPreviewConfig: ClockPreviewConfig,
-            statusBarHeight: Int,
-        ): Int {
-            return if (clockPreviewConfig.isShadeLayoutWide) {
-                getDimen(clockPreviewConfig.previewContext, "keyguard_split_shade_top_margin") -
-                    if (clockPreviewConfig.isSceneContainerFlagEnabled) statusBarHeight else 0
-            } else {
-                getDimen(clockPreviewConfig.previewContext, "keyguard_clock_top_margin") +
-                    if (!clockPreviewConfig.isSceneContainerFlagEnabled) statusBarHeight else 0
-            }
-        }
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt
index 94e669f..c705c51 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockPreviewConfig.kt
@@ -17,10 +17,24 @@
 package com.android.systemui.plugins.clocks
 
 import android.content.Context
+import com.android.internal.policy.SystemBarUtils
+import com.android.systemui.plugins.clocks.ContextExt.getDimen
 
 data class ClockPreviewConfig(
-    val previewContext: Context,
+    val context: Context,
     val isShadeLayoutWide: Boolean,
     val isSceneContainerFlagEnabled: Boolean = false,
     val lockId: Int? = null,
-)
+) {
+    fun getSmallClockTopPadding(
+        statusBarHeight: Int = SystemBarUtils.getStatusBarHeight(context)
+    ): Int {
+        return if (isShadeLayoutWide) {
+            context.getDimen("keyguard_split_shade_top_margin") -
+                if (isSceneContainerFlagEnabled) statusBarHeight else 0
+        } else {
+            context.getDimen("keyguard_clock_top_margin") +
+                if (!isSceneContainerFlagEnabled) statusBarHeight else 0
+        }
+    }
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ContextExt.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ContextExt.kt
new file mode 100644
index 0000000..17a1bfc
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ContextExt.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package com.android.systemui.plugins.clocks
+
+import android.content.Context
+
+object ContextExt {
+    fun Context.getId(name: String): Int {
+        val res = packageManager.getResourcesForApplication(packageName)
+        return res.getIdentifier(name, "id", packageName)
+    }
+
+    fun Context.getDimen(name: String): Int {
+        val id = resources.getIdentifier(name, "dimen", packageName)
+        return if (id == 0) 0 else resources.getDimensionPixelSize(id)
+    }
+}
diff --git a/packages/SystemUI/plugin_core/processor/src/com/android/systemui/plugins/processor/ProtectedPluginProcessor.kt b/packages/SystemUI/plugin_core/processor/src/com/android/systemui/plugins/processor/ProtectedPluginProcessor.kt
index 6b54d89..d93f7d3 100644
--- a/packages/SystemUI/plugin_core/processor/src/com/android/systemui/plugins/processor/ProtectedPluginProcessor.kt
+++ b/packages/SystemUI/plugin_core/processor/src/com/android/systemui/plugins/processor/ProtectedPluginProcessor.kt
@@ -33,9 +33,10 @@
 
 /**
  * [ProtectedPluginProcessor] generates a proxy implementation for interfaces annotated with
- * [ProtectedInterface] which catches [LinkageError]s generated by the proxied target. This protects
- * the plugin host from crashing due to out-of-date plugin code, where some call has changed so that
- * the [ClassLoader] can no longer resolve it correctly.
+ * [ProtectedInterface] which catches [Exception]s generated by the proxied target. Production
+ * plugin interfaces should use this to catch [LinkagError]s as that protects the plugin host from
+ * crashing due to out-of-date plugin code, where some call has changed so that the [ClassLoader] is
+ * no longer able to resolve it correctly.
  *
  * [PluginInstance] observes these failures via [ProtectedMethodListener] and unloads the plugin in
  * question to prevent further issues. This persists through further load/unload requests.
@@ -61,6 +62,7 @@
         val sourcePkg: String,
         val sourceName: String,
         val outputName: String,
+        val exTypeAttr: ProtectedInterface,
     )
 
     override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
@@ -68,10 +70,19 @@
         val additionalImports = mutableSetOf<String>()
         for (attr in annotations) {
             for (target in roundEnv.getElementsAnnotatedWith(attr)) {
+                // Find the target exception types to be used
+                var exTypeAttr = target.getAnnotation(ProtectedInterface::class.java)
+                if (exTypeAttr == null || exTypeAttr.exTypes.size == 0) {
+                    exTypeAttr = ProtectedInterface.Default
+                }
+
                 val sourceName = "${target.simpleName}"
                 val outputName = "${sourceName}Protector"
                 val pkg = (target.getEnclosingElement() as PackageElement).qualifiedName.toString()
-                targets.put("$target", TargetData(attr, target, pkg, sourceName, outputName))
+                targets.put(
+                    "$target",
+                    TargetData(attr, target, pkg, sourceName, outputName, exTypeAttr),
+                )
 
                 // This creates excessive imports, but it should be fine
                 additionalImports.add("$pkg.$sourceName")
@@ -80,7 +91,7 @@
         }
 
         if (targets.size <= 0) return false
-        for ((_, sourceType, sourcePkg, sourceName, outputName) in targets.values) {
+        for ((_, sourceType, sourcePkg, sourceName, outputName, exTypeAttr) in targets.values) {
             // Find all methods in this type and all super types to that need to be implemented
             val types = ArrayDeque<TypeMirror>().apply { addLast(sourceType.asType()) }
             val impAttrs = mutableListOf<GeneratedImport>()
@@ -105,7 +116,6 @@
 
                 // Imports used by the proxy implementation
                 line("import android.util.Log;")
-                line("import java.lang.LinkageError;")
                 line("import com.android.systemui.plugins.PluginWrapper;")
                 line("import com.android.systemui.plugins.ProtectedPluginListener;")
                 line()
@@ -118,6 +128,14 @@
                     line()
                 }
 
+                // Imports of caught exceptions
+                if (exTypeAttr.exTypes.size > 0) {
+                    for (exType in exTypeAttr.exTypes) {
+                        line("import $exType;")
+                    }
+                    line()
+                }
+
                 // Imports declared via @GeneratedImport
                 if (impAttrs.size > 0) {
                     for (impAttr in impAttrs) {
@@ -232,11 +250,14 @@
                             // Protect callsite in try/catch block
                             braceBlock("try") { line(callStatement) }
 
-                            // Notify listener when a LinkageError is caught
-                            braceBlock("catch (LinkageError ex)") {
-                                line("Log.wtf(CLASS, \"Failed to execute: \" + METHOD, ex);")
-                                line("mHasError = mListener.onFail(CLASS, METHOD, ex);")
-                                line(errorStatement)
+                            // Notify listener when a target exception is caught
+                            for (exType in exTypeAttr.exTypes) {
+                                val simpleName = exType.substringAfterLast(".")
+                                braceBlock("catch ($simpleName ex)") {
+                                    line("Log.wtf(CLASS, \"Failed to execute: \" + METHOD, ex);")
+                                    line("mHasError = mListener.onFail(CLASS, METHOD, ex);")
+                                    line(errorStatement)
+                                }
                             }
                         }
                         line()
diff --git a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/ProtectedPluginListener.kt b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/ProtectedPluginListener.kt
index 3a1f251..8e2528f 100644
--- a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/ProtectedPluginListener.kt
+++ b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/ProtectedPluginListener.kt
@@ -16,12 +16,11 @@
 /** Listener for events from proxy types generated by [ProtectedPluginProcessor]. */
 interface ProtectedPluginListener {
     /**
-     * Called when a method call produces a [LinkageError] before returning. This callback is
-     * provided so that the host application can terminate the plugin or log the error as
-     * appropriate.
+     * Called when a method call produces a [Exception] before returning. This callback is provided
+     * so that the host application can terminate the plugin or log the error as appropriate.
      *
      * @return true to terminate all methods within this object; false if the error is recoverable
      *   and the proxied plugin should continue to operate as normal.
      */
-    fun onFail(className: String, methodName: String, failure: LinkageError): Boolean
+    fun onFail(className: String, methodName: String, failure: Throwable): Boolean
 }
diff --git a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/annotations/ProtectedInterface.kt b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/annotations/ProtectedInterface.kt
index 12a977d..dc2ea8c 100644
--- a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/annotations/ProtectedInterface.kt
+++ b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/annotations/ProtectedInterface.kt
@@ -15,11 +15,15 @@
 
 /**
  * This annotation marks denotes that an interface should use a proxy layer to protect the plugin
- * host from crashing due to [LinkageError]s originating within the plugin's implementation.
+ * host from crashing due to the [Exception] types originating within the plugin's implementation.
  */
 @Target(AnnotationTarget.CLASS)
 @Retention(AnnotationRetention.BINARY)
-annotation class ProtectedInterface
+annotation class ProtectedInterface(vararg val exTypes: String) {
+    companion object {
+        val Default = ProtectedInterface("java.lang.Exception", "java.lang.LinkageError")
+    }
+}
 
 /**
  * This annotation specifies any additional imports that the processor will require when generating
@@ -32,9 +36,9 @@
 annotation class GeneratedImport(val extraImport: String)
 
 /**
- * This annotation provides default values to return when the proxy implementation catches a
- * [LinkageError]. The string specified should be a simple but valid java statement. In most cases
- * it should be a return statement of the appropriate type, but in some cases throwing a known
+ * This annotation provides default values to return when the proxy implementation catches a target
+ * [Exception]. The string specified should be a simple but valid java statement. In most cases it
+ * should be a return statement of the appropriate type, but in some cases throwing a known
  * exception type may be preferred.
  *
  * This annotation is not required for methods that return void, but will behave the same way.
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml
deleted file mode 100644
index f68ab81..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_presentation.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-**
-** Copyright 2023, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<androidx.constraintlayout.widget.ConstraintLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/presentation"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <com.android.keyguard.KeyguardStatusView
-        android:id="@+id/clock"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_gravity="center"
-        android:orientation="vertical"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintDimensionRatio="1:1"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent">
-
-
-        <include
-            android:id="@+id/keyguard_clock_container"
-            layout="@layout/keyguard_clock_switch"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"/>
-    </com.android.keyguard.KeyguardStatusView>
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
deleted file mode 100644
index 8bef475..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2018, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is a view that shows clock information in Keyguard. -->
-<com.android.keyguard.KeyguardClockSwitch
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/keyguard_clock_container"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:clipChildren="false"
-    android:layout_gravity="center_horizontal|top">
-    <com.android.keyguard.KeyguardClockFrame
-        android:id="@id/lockscreen_clock_view"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/small_clock_height"
-        android:layout_alignParentStart="true"
-        android:layout_alignParentTop="true"
-        android:clipChildren="false"
-        android:paddingStart="@dimen/clock_padding_start"
-        android:visibility="invisible" />
-    <com.android.keyguard.KeyguardClockFrame
-        android:id="@id/lockscreen_clock_view_large"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clipChildren="false"
-        android:visibility="gone" />
-
-    <!-- Not quite optimal but needed to translate these items as a group. The
-         NotificationIconContainer has its own logic for translation. -->
-    <com.android.keyguard.KeyguardStatusAreaView
-        android:id="@+id/keyguard_status_area"
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentStart="true"
-        android:layout_below="@id/lockscreen_clock_view">
-
-      <include layout="@layout/keyguard_slice_view"
-               android:id="@+id/keyguard_slice_view"
-               android:layout_width="match_parent"
-               android:layout_height="wrap_content" />
-
-      <com.android.systemui.statusbar.phone.NotificationIconContainer
-          android:id="@+id/left_aligned_notification_icon_container"
-          android:layout_width="match_parent"
-          android:layout_height="@dimen/notification_shelf_height"
-          android:paddingStart="@dimen/below_clock_padding_start_icons"
-          android:visibility="invisible"
-          />
-    </com.android.keyguard.KeyguardStatusAreaView>
-</com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
deleted file mode 100644
index 8a0dd12..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is a view that shows general status information in Keyguard. -->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/presentation"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <!-- This is mostly keyguard_status_view.xml with minor modifications -->
-    <com.android.keyguard.KeyguardStatusView
-        android:id="@+id/clock"
-        android:orientation="vertical"
-        android:layout_width="@dimen/keyguard_presentation_width"
-        android:layout_height="wrap_content">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <include
-                layout="@layout/keyguard_clock_switch"
-                android:id="@+id/keyguard_clock_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-            <ImageView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="24dp"
-                android:layout_gravity="center_horizontal"
-                android:src="@drawable/kg_security_lock_normal" />
-        </LinearLayout>
-    </com.android.keyguard.KeyguardStatusView>
-
-</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml
index 7c5dbc2..99b98dd 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_slice_view.xml
@@ -20,6 +20,7 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <com.android.keyguard.KeyguardSliceView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyguard_slice_view"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="start"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
deleted file mode 100644
index e6122a0..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License")
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- This is a view that shows general status information in Keyguard. -->
-<com.android.keyguard.KeyguardStatusView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/keyguard_status_view"
-    android:orientation="vertical"
-    systemui:layout_constraintStart_toStartOf="parent"
-    systemui:layout_constraintEnd_toEndOf="parent"
-    systemui:layout_constraintTop_toTopOf="parent"
-    android:layout_marginHorizontal="@dimen/status_view_margin_horizontal"
-    android:clipChildren="false"
-    android:layout_width="0dp"
-    android:layout_height="wrap_content">
-    <com.android.keyguard.KeyguardStatusContainer
-        android:id="@+id/status_view_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:orientation="vertical">
-        <include
-            layout="@layout/keyguard_clock_switch"
-            android:id="@+id/keyguard_clock_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-        <FrameLayout
-            android:id="@id/status_view_media_container"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:padding="@dimen/qs_media_padding"
-            />
-    </com.android.keyguard.KeyguardStatusContainer>
-</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/SystemUI/res-product/values-af/strings.xml b/packages/SystemUI/res-product/values-af/strings.xml
index e49c890..bd05051 100644
--- a/packages/SystemUI/res-product/values-af/strings.xml
+++ b/packages/SystemUI/res-product/values-af/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontsluit jou toestel vir meer opsies"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Speel tans op hierdie foon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Speel tans op hierdie tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Jy kan hierdie foon met Kry My Toestel opspoor selfs wanneer dit afgeskakel is"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Jy kan hierdie tablet met Kry My Toestel opspoor selfs wanneer dit afgeskakel is"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-am/strings.xml b/packages/SystemUI/res-product/values-am/strings.xml
index 49e5d52..f34708e 100644
--- a/packages/SystemUI/res-product/values-am/strings.xml
+++ b/packages/SystemUI/res-product/values-am/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ለተጨማሪ አማራጮች የእርስዎን መሣሪያ ይክፈቱ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"በዚህ ስልክ ላይ በመጫወት ላይ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"በዚህ ጡባዊ ላይ በመጫወት ላይ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ይህን ስልክ ኃይል ጠፍቶ ቢሆን እንኳን የእኔን መሣሪያ አግኝ በሚለው አማካኝነት ማግኘት ይችላሉ"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ይህን ጡባዊ ኃይል ጠፍቶ ቢሆን እንኳን የእኔን መሣሪያ አግኝ በሚለው አማካኝነት ማግኘት ይችላሉ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ar/strings.xml b/packages/SystemUI/res-product/values-ar/strings.xml
index d365ef2..7332ec8 100644
--- a/packages/SystemUI/res-product/values-ar/strings.xml
+++ b/packages/SystemUI/res-product/values-ar/strings.xml
@@ -66,4 +66,8 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"يمكنك فتح قفل جهازك للوصول إلى مزيد من الخيارات."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"جارٍ تشغيل الوسائط على هذا الهاتف."</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"جارٍ تشغيل الوسائط على هذا الجهاز اللوحي."</string>
+    <!-- no translation found for finder_active (2734050945122991747) -->
+    <skip />
+    <!-- no translation found for finder_active (8045583079989970505) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res-product/values-as/strings.xml b/packages/SystemUI/res-product/values-as/strings.xml
index 40aab2f..6997b5f 100644
--- a/packages/SystemUI/res-product/values-as/strings.xml
+++ b/packages/SystemUI/res-product/values-as/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"অধিক বিকল্পৰ বাবে আপোনাৰ ডিভাইচটো আনলক কৰক"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"এই ফ’নটোত প্লে’ কৰি থকা হৈছে"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"এই টেবলেটটোত প্লে’ কৰি থকা হৈছে"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"পাৱাৰ অফ কৰা থাকিলেও Find My Deviceৰ জৰিয়তে আপুনি এই ফ’নটোৰ অৱস্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"পাৱাৰ অফ কৰা থাকিলেও Find My Deviceৰ জৰিয়তে আপুনি এই টেবলেটটোৰ অৱস্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-az/strings.xml b/packages/SystemUI/res-product/values-az/strings.xml
index b7e93fd..dedc138 100644
--- a/packages/SystemUI/res-product/values-az/strings.xml
+++ b/packages/SystemUI/res-product/values-az/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Daha çox seçim üçün cihazı kiliddən çıxarın"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Bu telefonda oxudulur"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Bu planşetdə oxudulur"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Bu telefon sönülü olsa belə, Cihazın Tapılması ilə onu tapa bilərsiniz"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Bu planşet sönülü olsa belə, Cihazın Tapılması ilə onu tapa bilərsiniz"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
index 067c16b..f598319 100644
--- a/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-product/values-b+sr+Latn/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za još opcija"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Pušta se na ovom telefonu"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Pušta se na ovom tabletu"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Možete da locirate ovaj telefon pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Možete da locirate ovaj tablet pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-be/strings.xml b/packages/SystemUI/res-product/values-be/strings.xml
index 9b2658e..3ff833e 100644
--- a/packages/SystemUI/res-product/values-be/strings.xml
+++ b/packages/SystemUI/res-product/values-be/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Каб адкрыць іншыя параметры, разблакіруйце прыладу"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Прайграецца на гэтым тэлефоне"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Прайграецца на гэтым планшэце"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Вы можаце знайсці свой тэлефон з дапамогай праграмы \"Знайсці прыладу\", нават калі ён выключаны"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Вы можаце знайсці свой планшэт з дапамогай праграмы \"Знайсці прыладу\", нават калі ён выключаны"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-bg/strings.xml b/packages/SystemUI/res-product/values-bg/strings.xml
index 039ece7..62bd273 100644
--- a/packages/SystemUI/res-product/values-bg/strings.xml
+++ b/packages/SystemUI/res-product/values-bg/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отключете устройството си за още опции"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Възпроизвежда се на този телефон"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Възпроизвежда се на този таблет"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Можете да откриете този телефон посредством „Намиране на устройството ми“ дори когато е изключен"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Можете да откриете този таблет посредством „Намиране на устройството ми“ дори когато е изключен"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-bn/strings.xml b/packages/SystemUI/res-product/values-bn/strings.xml
index 19165ef..5d184f8 100644
--- a/packages/SystemUI/res-product/values-bn/strings.xml
+++ b/packages/SystemUI/res-product/values-bn/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"আরও বিকল্প দেখতে আপনার ডিভাইস আনলক করুন"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"এই ফোনে চালানো হচ্ছে"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"এই ট্যাবলেটে চালানো হচ্ছে"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Find My Device-এর মাধ্যমে, এই ফোনটি বন্ধ করা থাকলেও তার লোকেশন শনাক্ত করতে পারবেন"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Find My Device-এর মাধ্যমে, এই ট্যাবলেটটি বন্ধ করা থাকলেও তার লোকেশন শনাক্ত করতে পারবেন"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-bs/strings.xml b/packages/SystemUI/res-product/values-bs/strings.xml
index 1c1316f..cc98ad8 100644
--- a/packages/SystemUI/res-product/values-bs/strings.xml
+++ b/packages/SystemUI/res-product/values-bs/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Otključajte uređaj za više opcija"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Reproducira se na ovom telefonu"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Reproducira se na ovom tabletu"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Možete pronaći telefon putem usluge Pronađi moj uređaj čak i kada je isključen"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Možete pronaći tablet putem usluge Pronađi moj uređaj čak i kada je isključen"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ca/strings.xml b/packages/SystemUI/res-product/values-ca/strings.xml
index cfec9b2..c8e03c3 100644
--- a/packages/SystemUI/res-product/values-ca/strings.xml
+++ b/packages/SystemUI/res-product/values-ca/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueja el teu dispositiu per veure més opcions"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"S\'està reproduint en aquest telèfon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"S\'està reproduint en aquesta tauleta"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Pots localitzar aquest telèfon amb Troba el meu dispositiu fins i tot quan estigui apagat"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Pots localitzar aquesta tauleta amb Troba el meu dispositiu fins i tot quan estigui apagada"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-cs/strings.xml b/packages/SystemUI/res-product/values-cs/strings.xml
index ffefb98..dde826d 100644
--- a/packages/SystemUI/res-product/values-cs/strings.xml
+++ b/packages/SystemUI/res-product/values-cs/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Chcete-li zobrazit další možnosti, odemkněte zařízení"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Přehrávání na tomto telefonu"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Přehrávání na tomto tabletu"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Tento telefon můžete pomocí funkce Najdi moje zařízení najít, i když je vypnutý"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Tento tablet můžete pomocí funkce Najdi moje zařízení najít, i když je vypnutý"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-da/strings.xml b/packages/SystemUI/res-product/values-da/strings.xml
index 9bed837..b0bde5d 100644
--- a/packages/SystemUI/res-product/values-da/strings.xml
+++ b/packages/SystemUI/res-product/values-da/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås din enhed op for at se flere valgmuligheder"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Afspilles på denne telefon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Afspilles på denne tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Du kan finde denne telefon med Find min enhed, også selvom den er slukket"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Du kan finde denne tablet med Find min enhed, også selvom den er slukket"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-de/strings.xml b/packages/SystemUI/res-product/values-de/strings.xml
index acf27a8d..2f2b3cb 100644
--- a/packages/SystemUI/res-product/values-de/strings.xml
+++ b/packages/SystemUI/res-product/values-de/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Entsperre dein Gerät für weitere Optionen"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Wiedergabe läuft auf diesem Smartphone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Wiedergabe läuft auf diesem Tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Du kannst dieses Smartphone über „Mein Gerät finden“ orten, auch wenn es ausgeschaltet ist"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Du kannst dieses Tablet über „Mein Gerät finden“ orten, auch wenn es ausgeschaltet ist"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-el/strings.xml b/packages/SystemUI/res-product/values-el/strings.xml
index 67bdbcf..15ce5ab8 100644
--- a/packages/SystemUI/res-product/values-el/strings.xml
+++ b/packages/SystemUI/res-product/values-el/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ξεκλειδώστε τη συσκευή σας για περισσότερες επιλογές"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Αναπαραγωγή σε αυτό το τηλέφωνο"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Αναπαραγωγή σε αυτό το tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Μπορείτε να εντοπίσετε το συγκεκριμένο τηλέφωνο με την Εύρεση συσκευής ακόμα και όταν είναι απενεργοποιημένο"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Μπορείτε να εντοπίσετε το συγκεκριμένο tablet με την Εύρεση συσκευής ακόμα και όταν είναι απενεργοποιημένο"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-en-rAU/strings.xml b/packages/SystemUI/res-product/values-en-rAU/strings.xml
index 1373251..7372e41 100644
--- a/packages/SystemUI/res-product/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rAU/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Playing on this phone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Playing on this tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"You can locate this phone with Find My Device even when powered off"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"You can locate this tablet with Find My Device even when powered off"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-en-rCA/strings.xml b/packages/SystemUI/res-product/values-en-rCA/strings.xml
index eaa5de0..6eaa2e4 100644
--- a/packages/SystemUI/res-product/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rCA/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Playing on this phone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Playing on this tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"You can locate this phone with Find My Device even when powered off"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"You can locate this tablet with Find My Device even when powered off"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-en-rGB/strings.xml b/packages/SystemUI/res-product/values-en-rGB/strings.xml
index 1373251..7372e41 100644
--- a/packages/SystemUI/res-product/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rGB/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Playing on this phone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Playing on this tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"You can locate this phone with Find My Device even when powered off"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"You can locate this tablet with Find My Device even when powered off"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-en-rIN/strings.xml b/packages/SystemUI/res-product/values-en-rIN/strings.xml
index 1373251..7372e41 100644
--- a/packages/SystemUI/res-product/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-product/values-en-rIN/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Unlock your device for more options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Playing on this phone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Playing on this tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"You can locate this phone with Find My Device even when powered off"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"You can locate this tablet with Find My Device even when powered off"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-es-rUS/strings.xml b/packages/SystemUI/res-product/values-es-rUS/strings.xml
index 7ee96b2..99bbca2 100644
--- a/packages/SystemUI/res-product/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-product/values-es-rUS/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Reproduciendo en este teléfono"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Reproduciendo en esta tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Puedes ubicar este teléfono con Encontrar mi dispositivo, incluso si está apagado"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Puedes ubicar esta tablet con Encontrar mi dispositivo, incluso si está apagada"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-es/strings.xml b/packages/SystemUI/res-product/values-es/strings.xml
index 90ebe96..4fc1bf5 100644
--- a/packages/SystemUI/res-product/values-es/strings.xml
+++ b/packages/SystemUI/res-product/values-es/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea el dispositivo para ver más opciones"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Reproduciendo en este teléfono"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Reproduciendo en esta tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Puedes localizar este teléfono con Encontrar mi dispositivo, aunque esté apagado"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Puedes localizar esta tablet con Encontrar mi dispositivo, aunque esté apagada"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-et/strings.xml b/packages/SystemUI/res-product/values-et/strings.xml
index be1e084..1afa497 100644
--- a/packages/SystemUI/res-product/values-et/strings.xml
+++ b/packages/SystemUI/res-product/values-et/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lisavalikute nägemiseks avage oma seade"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Esitatakse selles telefonis"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Esitatakse selles tahvelarvutis"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Saate selle telefoni funktsiooniga Leia mu seade leida ka siis, kui see on välja lülitatud"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Saate selle tahvelarvuti funktsiooniga Leia mu seade leida ka siis, kui see on välja lülitatud"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-eu/strings.xml b/packages/SystemUI/res-product/values-eu/strings.xml
index abd3f39..c093085 100644
--- a/packages/SystemUI/res-product/values-eu/strings.xml
+++ b/packages/SystemUI/res-product/values-eu/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desblokeatu gailua aukera gehiago ikusteko"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Telefono honetan erreproduzitzen"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Tableta honetan erreproduzitzen"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Itzalita badago ere aurki dezakezu telefonoa Bilatu nire gailua erabilita"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Itzalita badago ere aurki dezakezu tableta Bilatu nire gailua erabilita"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-fa/strings.xml b/packages/SystemUI/res-product/values-fa/strings.xml
index 40f8d0d..e08fe4fb 100644
--- a/packages/SystemUI/res-product/values-fa/strings.xml
+++ b/packages/SystemUI/res-product/values-fa/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"برای گزینه‌های بیشتر، قفل دستگاه را باز کنید"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"درحال پخش در این تلفن"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"درحال پخش در این رایانه لوحی"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"حتی وقتی این تلفن خاموش است، می‌توانید با «پیدا کردن دستگاهم» آن را مکان‌یابی کنید"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"حتی وقتی این رایانه لوحی خاموش است، می‌توانید با «پیدا کردن دستگاهم» آن را مکان‌یابی کنید"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-fi/strings.xml b/packages/SystemUI/res-product/values-fi/strings.xml
index 3ed7f6d..1a786c6 100644
--- a/packages/SystemUI/res-product/values-fi/strings.xml
+++ b/packages/SystemUI/res-product/values-fi/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Avaa laitteen lukitus, niin näet enemmän vaihtoehtoja"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Toistetaan tällä puhelimella"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Toistetaan tällä tabletilla"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Voit löytää tämän puhelimen Paikanna laite ‑sovelluksella, vaikka se olisi sammutettuna"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Voit löytää tämän tabletin Paikanna laite ‑sovelluksella, vaikka se olisi sammutettuna"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-fr-rCA/strings.xml b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
index eec07a5..98c8b615 100644
--- a/packages/SystemUI/res-product/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-product/values-fr-rCA/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour afficher davantage d\'options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Lecture sur ce téléphone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Lecture sur cette tablette"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Vous pouvez localiser ce téléphone à l\'aide de Localiser mon appareil, même lorsqu\'il est éteint"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Vous pouvez localiser cette tablette à l\'aide de Localiser mon appareil, même lorsqu\'elle est éteinte"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-fr/strings.xml b/packages/SystemUI/res-product/values-fr/strings.xml
index eedc182..d0383f2 100644
--- a/packages/SystemUI/res-product/values-fr/strings.xml
+++ b/packages/SystemUI/res-product/values-fr/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Déverrouillez votre appareil pour obtenir plus d\'options"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Lecture sur ce téléphone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Lecture sur cette tablette…"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Vous pouvez localiser ce téléphone avec Localiser mon appareil même lorsqu\'il est éteint"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Vous pouvez localiser cette tablette avec Localiser mon appareil même lorsqu\'elle est éteinte"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-gl/strings.xml b/packages/SystemUI/res-product/values-gl/strings.xml
index 67be4b2..27f3500 100644
--- a/packages/SystemUI/res-product/values-gl/strings.xml
+++ b/packages/SystemUI/res-product/values-gl/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloquea o dispositivo para ver máis opcións"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Reproducindo contido neste teléfono"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Reproducindo contido nesta tableta"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Podes atopar este teléfono (mesmo se está apagado) con Localizar o meu dispositivo"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Podes atopar esta tableta (mesmo se está apagada) con Localizar o meu dispositivo"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-gu/strings.xml b/packages/SystemUI/res-product/values-gu/strings.xml
index d43c3d3..59dc000 100644
--- a/packages/SystemUI/res-product/values-gu/strings.xml
+++ b/packages/SystemUI/res-product/values-gu/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"વધુ વિકલ્પો માટે તમારા ડિવાઇસને અનલૉક કરો"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"આ ફોન પર ચલાવવામાં આવી રહ્યું છે"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"આ ટૅબ્લેટ પર ચલાવવામાં આવી રહ્યું છે"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"આ ફોનનો પાવર બંધ હોય ત્યારે પણ Find My Device વડે તમે તેનું લોકેશન જાણી શકો છો"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"આ ટૅબ્લેટનો પાવર બંધ હોય ત્યારે પણ Find My Device વડે તમે તેનું લોકેશન જાણી શકો છો"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-hi/strings.xml b/packages/SystemUI/res-product/values-hi/strings.xml
index dab5f57..92d5505 100644
--- a/packages/SystemUI/res-product/values-hi/strings.xml
+++ b/packages/SystemUI/res-product/values-hi/strings.xml
@@ -66,4 +66,8 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ज़्यादा विकल्प देखने के लिए, अपना डिवाइस अनलॉक करें"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"मीडिया इस फ़ोन पर चल रहा है"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"मीडिया इस टैबलेट पर चल रहा है"</string>
+    <!-- no translation found for finder_active (2734050945122991747) -->
+    <skip />
+    <!-- no translation found for finder_active (8045583079989970505) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res-product/values-hr/strings.xml b/packages/SystemUI/res-product/values-hr/strings.xml
index 8be9a22..f59cc55 100644
--- a/packages/SystemUI/res-product/values-hr/strings.xml
+++ b/packages/SystemUI/res-product/values-hr/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za više opcija otključajte uređaj"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Reproducira se na ovom telefonu"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Reproducira se na ovom tabletu"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Telefon možete pronaći pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Tablet možete pronaći pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-hu/strings.xml b/packages/SystemUI/res-product/values-hu/strings.xml
index 97feff8..189d3ff 100644
--- a/packages/SystemUI/res-product/values-hu/strings.xml
+++ b/packages/SystemUI/res-product/values-hu/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"További lehetőségekért oldja fel az eszközt"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Lejátszás ezen a telefonon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Lejátszás ezen a táblagépen"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"A Készülékkereső segítségével akár a kikapcsolt telefon helyét is meghatározhatja."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"A Készülékkereső segítségével akár a kikapcsolt táblagép helyét is meghatározhatja."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-hy/strings.xml b/packages/SystemUI/res-product/values-hy/strings.xml
index 8e4c75a..deea8bc 100644
--- a/packages/SystemUI/res-product/values-hy/strings.xml
+++ b/packages/SystemUI/res-product/values-hy/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ապակողպեք ձեր սարքը՝ լրացուցիչ կարգավորումները տեսնելու համար"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Նվագարկվում է այս հեռախոսում"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Նվագարկվում է այս պլանշետում"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"«Գտնել իմ սարքը» ծառայության օգնությամբ դուք կարող եք տեղորոշել այս հեռախոսը, նույնիսկ եթե այն անջատված է"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"«Գտնել իմ սարքը» ծառայության օգնությամբ դուք կարող եք տեղորոշել այս պլանշետը, նույնիսկ եթե այն անջատված է"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-in/strings.xml b/packages/SystemUI/res-product/values-in/strings.xml
index 2224810..45d7316 100644
--- a/packages/SystemUI/res-product/values-in/strings.xml
+++ b/packages/SystemUI/res-product/values-in/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci perangkat untuk melihat opsi lainnya"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Diputar di ponsel ini"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Diputar di tablet ini"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Anda dapat menemukan lokasi ponsel ini dengan aplikasi Temukan Perangkat Saya meskipun ponsel dimatikan"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Anda dapat menemukan lokasi tablet ini dengan aplikasi Temukan Perangkat Saya meskipun tablet dimatikan"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-is/strings.xml b/packages/SystemUI/res-product/values-is/strings.xml
index a39dd2d..d0673a2 100644
--- a/packages/SystemUI/res-product/values-is/strings.xml
+++ b/packages/SystemUI/res-product/values-is/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Taktu tækið úr lás til að fá fleiri valkosti"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Í spilun í þessum síma"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Í spilun í þessari spjaldtölvu"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Þú getur fundið þennan síma með „Finna tækið mitt“, jafnvel þótt slökkt sé á honum"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Þú getur fundið þessa spjaldtölvu með „Finna tækið mitt“, jafnvel þótt slökkt sé á henni"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-it/strings.xml b/packages/SystemUI/res-product/values-it/strings.xml
index a9fd80b..8814fbe 100644
--- a/packages/SystemUI/res-product/values-it/strings.xml
+++ b/packages/SystemUI/res-product/values-it/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Sblocca il dispositivo per visualizzare altre opzioni"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"In riproduzione su questo telefono"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"In riproduzione su questo tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Puoi trovare questo smartphone tramite Trova il mio dispositivo anche quando è spento"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Puoi trovare questo tablet tramite Trova il mio dispositivo anche quando è spento"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-iw/strings.xml b/packages/SystemUI/res-product/values-iw/strings.xml
index 5049d10..0b289b7 100644
--- a/packages/SystemUI/res-product/values-iw/strings.xml
+++ b/packages/SystemUI/res-product/values-iw/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"לאפשרויות נוספות, יש לבטל את נעילת המכשיר"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"פועלת בטלפון הזה"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"פועלת בטאבלט הזה"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"יש לך אפשרות לאתר את הטלפון הזה בעזרת שירות \"איפה המכשיר שלי\" גם כשהטלפון כבוי"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"יש לך אפשרות לאתר את הטאבלט הזה בעזרת שירות \"איפה המכשיר שלי\" גם כשהטאבלט כבוי"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ja/strings.xml b/packages/SystemUI/res-product/values-ja/strings.xml
index cd7f1c1..361238a 100644
--- a/packages/SystemUI/res-product/values-ja/strings.xml
+++ b/packages/SystemUI/res-product/values-ja/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"デバイスのロックを解除してその他のオプションを表示する"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"このスマートフォンで再生しています"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"このタブレットで再生しています"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"「デバイスを探す」を使うと、電源が OFF の状態でもこのスマートフォンの現在地を確認できます"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"「デバイスを探す」を使うと、電源が OFF の状態でもこのタブレットの現在地を確認できます"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ka/strings.xml b/packages/SystemUI/res-product/values-ka/strings.xml
index f007c4a..c99d347 100644
--- a/packages/SystemUI/res-product/values-ka/strings.xml
+++ b/packages/SystemUI/res-product/values-ka/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"მეტი ვარიანტის სანახავად განბლოკეთ თქვენი მოწყობილობა"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"უკრავს ამ ტელეფონზე"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"უკრავს ამ ტაბლეტზე"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"შეგიძლიათ დაადგინოთ ამ ტელეფონის მდებარეობა ფუნქციით „ჩემი მოწყობილობის პოვნა“, მაშინაც კი, როდესაც ის გამორთულია"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"შეგიძლიათ დაადგინოთ ამ ტაბლეტის მდებარეობა ფუნქციით „ჩემი მოწყობილობის პოვნა“, მაშინაც კი, როდესაც ის გამორთულია"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-kk/strings.xml b/packages/SystemUI/res-product/values-kk/strings.xml
index 83b2351..5f9a436 100644
--- a/packages/SystemUI/res-product/values-kk/strings.xml
+++ b/packages/SystemUI/res-product/values-kk/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Басқа опцияларды көру үшін құрылғы құлпын ашыңыз."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Осы телефонда ойнатылуда."</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Осы планшетте ойнатылуда."</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Сіз бұл телефонды, ол тіпті өшірулі тұрса да, Find My Device арқылы таба аласыз."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Сіз бұл планшетті, ол тіпті өшірулі тұрса да, Find My Device арқылы таба аласыз."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-km/strings.xml b/packages/SystemUI/res-product/values-km/strings.xml
index 34189d4..9916a5e 100644
--- a/packages/SystemUI/res-product/values-km/strings.xml
+++ b/packages/SystemUI/res-product/values-km/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ដោះសោ​ឧបករណ៍របស់អ្នក​សម្រាប់​ជម្រើសច្រើនទៀត"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"កំពុង​ចាក់​​នៅ​លើទូរសព្ទនេះ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"កំពុង​ចាក់​នៅលើ​ថេប្លេត​នេះ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"អ្នកអាចកំណត់ទីតាំងទូរសព្ទនេះដោយប្រើកម្មវិធីរកឧបករណ៍របស់ខ្ញុំ សូម្បីនៅពេលបិទថាមពល"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"អ្នកអាចកំណត់ទីតាំងថេប្លេតនេះដោយប្រើកម្មវិធីរកឧបករណ៍របស់ខ្ញុំ សូម្បីនៅពេលបិទថាមពល"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-kn/strings.xml b/packages/SystemUI/res-product/values-kn/strings.xml
index 4532d83..93a3263 100644
--- a/packages/SystemUI/res-product/values-kn/strings.xml
+++ b/packages/SystemUI/res-product/values-kn/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ಹೆಚ್ಚಿನ ಆಯ್ಕೆಗಳಿಗಾಗಿ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ಈ ಫೋನ್‌ನಲ್ಲಿ ಪ್ಲೇ ಆಗುತ್ತಿದೆ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ಈ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ಪವರ್ ಆಫ್ ಆಗಿರುವಾಗಲೂ ನೀವು Find My Device ಮೂಲಕ ಈ ಫೋನ್ ಅನ್ನು ಪತ್ತೆ ಮಾಡಬಹುದು"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ಪವರ್ ಆಫ್ ಆಗಿರುವಾಗಲೂ ನೀವು Find My Device ಮೂಲಕ ಈ ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಅನ್ನು ಪತ್ತೆ ಮಾಡಬಹುದು"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ko/strings.xml b/packages/SystemUI/res-product/values-ko/strings.xml
index c894120..ff48cfa 100644
--- a/packages/SystemUI/res-product/values-ko/strings.xml
+++ b/packages/SystemUI/res-product/values-ko/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"더 많은 옵션을 확인하려면 기기를 잠금 해제하세요."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"이 휴대전화에서 재생 중"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"이 태블릿에서 재생 중"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"전원이 꺼져 있을 때도 내 기기 찾기로 이 휴대전화를 찾을 수 있습니다."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"전원이 꺼져 있을 때도 내 기기 찾기로 이 태블릿을 찾을 수 있습니다."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index 11e7f6f..4b49689 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Дагы башка параметрлерди көрүү үчүн түзмөгүңүздүн кулпусун ачыңыз"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Ушул телефондо ойнотулууда"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Ушул планшетте ойнотулууда"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Бул телефон өчүк болсо да, аны \"Түзмөгүм кайда?\" кызматы аркылуу таба аласыз"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Бул планшет өчүк болсо да, аны \"Түзмөгүм кайда?\" кызматы аркылуу таба аласыз"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-lo/strings.xml b/packages/SystemUI/res-product/values-lo/strings.xml
index 958cf32..f194607 100644
--- a/packages/SystemUI/res-product/values-lo/strings.xml
+++ b/packages/SystemUI/res-product/values-lo/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ປົດລັອກອຸປະກອນຂອງທ່ານເພື່ອໃຊ້ຕົວເລືອກເພີ່ມເຕີມ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ກຳລັງຫຼິ້ນຢູ່ໂທລະສັບນີ້"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ກຳລັງຫຼິ້ນຢູ່ແທັບເລັດນີ້"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ທ່ານສາມາດຊອກຫາສະຖານທີ່ຂອງໂທລະສັບເຄື່ອງນີ້ໄດ້ດ້ວຍແອັບຊອກຫາອຸປະກອນຂອງຂ້ອຍເຖິງແມ່ນວ່າຈະປິດເຄື່ອງຢູ່ກໍຕາມ"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ທ່ານສາມາດຊອກຫາສະຖານທີ່ຂອງແທັບເລັດເຄື່ອງນີ້ໄດ້ດ້ວຍແອັບຊອກຫາອຸປະກອນຂອງຂ້ອຍເຖິງແມ່ນວ່າຈະປິດເຄື່ອງຢູ່ກໍຕາມ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-lt/strings.xml b/packages/SystemUI/res-product/values-lt/strings.xml
index 989e411..a5c0701 100644
--- a/packages/SystemUI/res-product/values-lt/strings.xml
+++ b/packages/SystemUI/res-product/values-lt/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atrakinkite įrenginį, kad galėtumėte naudoti daugiau parinkčių"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Leidžiama šiame telefone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Leidžiama šiame planšetiniame kompiuteryje"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Šį telefoną galite rasti naudodami programą „Rasti įrenginį“, net jei jis išjungtas"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Šį planšetinį kompiuterį galite rasti naudodami programą „Rasti įrenginį“, net jei jis išjungtas"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-lv/strings.xml b/packages/SystemUI/res-product/values-lv/strings.xml
index a18076a..73c81b4 100644
--- a/packages/SystemUI/res-product/values-lv/strings.xml
+++ b/packages/SystemUI/res-product/values-lv/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Atbloķējiet ierīci, lai skatītu citas opcijas."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Notiek atskaņošana šajā tālrunī"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Notiek atskaņošana šajā planšetdatorā"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Lietotni “Atrast ierīci” var izmantot šī tālruņa atrašanās vietas noteikšanai arī tad, ja tālrunis ir izslēgts."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Lietotni “Atrast ierīci” var izmantot šī planšetdatora atrašanās vietas noteikšanai arī tad, ja planšetdators ir izslēgts."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-mk/strings.xml b/packages/SystemUI/res-product/values-mk/strings.xml
index bb58df2..b45efe0 100644
--- a/packages/SystemUI/res-product/values-mk/strings.xml
+++ b/packages/SystemUI/res-product/values-mk/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Отклучето го вашиот уред за повеќе опции"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Пуштено на овој телефон"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Пуштено на овој таблет"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Може да го лоцирате телефонов со „Најди го мојот уред“ дури и кога е исклучен"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Може да го лоцирате таблетов со „Најди го мојот уред“ дури и кога е исклучен"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ml/strings.xml b/packages/SystemUI/res-product/values-ml/strings.xml
index 0fc494c..f33942f 100644
--- a/packages/SystemUI/res-product/values-ml/strings.xml
+++ b/packages/SystemUI/res-product/values-ml/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് നിങ്ങളുടെ ഉപകരണം അൺലോക്ക് ചെയ്യുക"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ഈ ഫോണിൽ പ്ലേ ചെയ്യുന്നു"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ഈ ടാബ്‌ലെറ്റിൽ പ്ലേ ചെയ്യുന്നു"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ഓഫായിരിക്കുമ്പോഴും Find My Device ഉപയോഗിച്ച് നിങ്ങൾക്ക് ഈ ഫോൺ കണ്ടെത്താനാകും"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ഓഫായിരിക്കുമ്പോഴും Find My Device ഉപയോഗിച്ച് നിങ്ങൾക്ക് ഈ ടാബ്‌ലെറ്റ് കണ്ടെത്താനാകും"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-mn/strings.xml b/packages/SystemUI/res-product/values-mn/strings.xml
index 179e816..06fe584 100644
--- a/packages/SystemUI/res-product/values-mn/strings.xml
+++ b/packages/SystemUI/res-product/values-mn/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Бусад сонголтыг харахын тулд төхөөрөмжийнхөө түгжээг тайлна уу"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Энэ утсан дээр тоглуулж байна"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Энэ таблет дээр тоглуулж байна"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Та энэ утсыг унтраалттай байсан ч Миний төхөөрөмжийг олохоор байршлыг нь тогтоох боломжтой"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Та энэ таблетыг унтраалттай байсан ч Миний төхөөрөмжийг олохоор байршлыг нь тогтоох боломжтой"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-mr/strings.xml b/packages/SystemUI/res-product/values-mr/strings.xml
index 821b303..9d49b51 100644
--- a/packages/SystemUI/res-product/values-mr/strings.xml
+++ b/packages/SystemUI/res-product/values-mr/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"आणखी पर्यायांसाठी तुमचे डिव्हाइस अनलॉक करा"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"या फोनवर प्ले होत आहे"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"या टॅबलेटवर प्ले होत आहे"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"तुम्ही हा फोन बंद असतानादेखील Find My Device वापरून तो शोधू शकता"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"तुम्ही हा टॅबलेट बंद असतानादेखील Find My Device वापरून तो शोधू शकता"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ms/strings.xml b/packages/SystemUI/res-product/values-ms/strings.xml
index ee10626..1c36f67 100644
--- a/packages/SystemUI/res-product/values-ms/strings.xml
+++ b/packages/SystemUI/res-product/values-ms/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Buka kunci peranti anda untuk mendapatkan lagi pilihan"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Dimainkan pada telefon ini"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Dimainkan pada tablet ini"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Anda boleh mengesan telefon ini dengan Find My Device walaupun apabila telefon ini dimatikan kuasa"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Anda boleh mengesan tablet ini dengan Find My Device walaupun apabila tablet ini dimatikan kuasa"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-my/strings.xml b/packages/SystemUI/res-product/values-my/strings.xml
index 9a61692..0b43c73 100644
--- a/packages/SystemUI/res-product/values-my/strings.xml
+++ b/packages/SystemUI/res-product/values-my/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"နောက်ထပ် ထိန်းချုပ်မှုများအတွက် သင့်စက်ကို လော့ခ်ဖွင့်ပါ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ဤဖုန်းတွင် ဖွင့်နေသည်"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ဤတက်ဘလက်တွင် ဖွင့်နေသည်"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤဖုန်းကို ရှာနိုင်သည်"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤတက်ဘလက်ကို ရှာနိုင်သည်"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-nb/strings.xml b/packages/SystemUI/res-product/values-nb/strings.xml
index aaa0a03..14fdccf 100644
--- a/packages/SystemUI/res-product/values-nb/strings.xml
+++ b/packages/SystemUI/res-product/values-nb/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås opp enheten din for å få flere alternativer"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Spilles av på denne telefonen"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Spilles av på dette nettbrettet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Du kan finne denne telefonen med Finn enheten min, selv når den er slått av"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Du kan finne dette nettbrettet med Finn enheten min, selv når det er slått av"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ne/strings.xml b/packages/SystemUI/res-product/values-ne/strings.xml
index 9bb0b6d..ea2f594 100644
--- a/packages/SystemUI/res-product/values-ne/strings.xml
+++ b/packages/SystemUI/res-product/values-ne/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"थप विकल्पहरू हेर्न आफ्नो डिभाइस अनलक गर्नुहोस्"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"यो फोनमा प्ले गरिँदै छ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"यो ट्याब्लेटमा प्ले गरिँदै छ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"तपाईं Find My Device प्रयोग गरी यो फोन अफ भए पनि यसको लोकेसन पत्ता लगाउन सक्नुहुन्छ"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"तपाईं Find My Device प्रयोग गरी यो ट्याब्लेट अफ भए पनि यसको लोकेसन पत्ता लगाउन सक्नुहुन्छ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-nl/strings.xml b/packages/SystemUI/res-product/values-nl/strings.xml
index f4b6eea..21464b3 100644
--- a/packages/SystemUI/res-product/values-nl/strings.xml
+++ b/packages/SystemUI/res-product/values-nl/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ontgrendel je apparaat voor meer opties"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Afspelen op deze telefoon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Afspelen op deze tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Je kunt deze telefoon vinden met Vind mijn apparaat, ook als die uitstaat"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Je kunt deze tablet vinden met Vind mijn apparaat, ook als die uitstaat"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index fd4d47b..61c2f34 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ଅଧିକ ବିକଳ୍ପ ପାଇଁ ଆପଣଙ୍କ ଡିଭାଇସ୍ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ଏହି ଫୋନରେ ପ୍ଲେ ହେଉଛି"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ଏହି ଟାବଲେଟରେ ପ୍ଲେ ହେଉଛି"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ପାୱାର ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପଣ Find My Device ମାଧ୍ୟମରେ ଏହି ଫୋନକୁ ଖୋଜିପାରିବେ"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ପାୱାର ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପଣ Find My Device ମାଧ୍ୟମରେ ଏହି ଟାବଲେଟକୁ ଖୋଜିପାରିବେ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-pa/strings.xml b/packages/SystemUI/res-product/values-pa/strings.xml
index 81b047c..321b72e 100644
--- a/packages/SystemUI/res-product/values-pa/strings.xml
+++ b/packages/SystemUI/res-product/values-pa/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ਇਸ ਫ਼ੋਨ \'ਤੇ ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ਇਸ ਟੈਬਲੈੱਟ \'ਤੇ ਚਲਾਇਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"ਬੰਦ ਹੋਣ \'ਤੇ ਵੀ, ਤੁਸੀਂ ਇਸ ਫ਼ੋਨ ਨੂੰ Find My Device ਦੀ ਮਦਦ ਨਾਲ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"ਬੰਦ ਹੋਣ \'ਤੇ ਵੀ, ਤੁਸੀਂ ਇਸ ਟੈਬਲੈੱਟ ਨੂੰ Find My Device ਦੀ ਮਦਦ ਨਾਲ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-pl/strings.xml b/packages/SystemUI/res-product/values-pl/strings.xml
index 4e5ad3f..2d5f4db 100644
--- a/packages/SystemUI/res-product/values-pl/strings.xml
+++ b/packages/SystemUI/res-product/values-pl/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Odblokuj urządzenie, by wyświetlić więcej opcji"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Odtwarzam na tym telefonie"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Odtwarzam na tym tablecie"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Możesz zlokalizować ten telefon w usłudze Znajdź moje urządzenie, nawet jeśli będzie wyłączony"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Możesz zlokalizować ten tablet w usłudze Znajdź moje urządzenie, nawet jeśli będzie wyłączony"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-pt-rBR/strings.xml b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
index 3d6d890..1a99a16 100644
--- a/packages/SystemUI/res-product/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rBR/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Tocando neste smartphone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia tocando neste tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Localize o tablet com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-pt-rPT/strings.xml b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
index 40c7e53..ad904db 100644
--- a/packages/SystemUI/res-product/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-product/values-pt-rPT/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie o dispositivo para obter mais opções."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"A reproduzir neste telemóvel"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"A reproduzir neste tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Pode localizar este telemóvel com o serviço Localizar o meu dispositivo mesmo quando está desligado"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Pode localizar este tablet com o serviço Localizar o meu dispositivo mesmo quando está desligado"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-pt/strings.xml b/packages/SystemUI/res-product/values-pt/strings.xml
index 3d6d890..1a99a16 100644
--- a/packages/SystemUI/res-product/values-pt/strings.xml
+++ b/packages/SystemUI/res-product/values-pt/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Desbloqueie seu dispositivo para ver mais opções"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Tocando neste smartphone"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Mídia tocando neste tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Localize o tablet com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ro/strings.xml b/packages/SystemUI/res-product/values-ro/strings.xml
index f10d5ca..077f53e 100644
--- a/packages/SystemUI/res-product/values-ro/strings.xml
+++ b/packages/SystemUI/res-product/values-ro/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Deblochează dispozitivul pentru mai multe opțiuni"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Se redă pe acest telefon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Se redă pe această tabletă"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Poți localiza telefonul folosind aplicația Găsește-mi dispozitivul chiar dacă este oprit"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Poți localiza tableta folosind aplicația Găsește-mi dispozitivul chiar dacă este oprită"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ru/strings.xml b/packages/SystemUI/res-product/values-ru/strings.xml
index ed9ad1a..beac51e 100644
--- a/packages/SystemUI/res-product/values-ru/strings.xml
+++ b/packages/SystemUI/res-product/values-ru/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Чтобы посмотреть дополнительные параметры, разблокируйте устройство."</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Воспроизводится на этом телефоне."</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Воспроизводится на этом планшете."</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"С помощью приложения \"Найти устройство\" вы можете узнать местоположение телефона, даже когда он выключен."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"С помощью приложения \"Найти устройство\" вы можете узнать местоположение планшета, даже когда он выключен."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-si/strings.xml b/packages/SystemUI/res-product/values-si/strings.xml
index f2c0f43..28de883 100644
--- a/packages/SystemUI/res-product/values-si/strings.xml
+++ b/packages/SystemUI/res-product/values-si/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"තව විකල්ප සඳහා ඔබේ උපාංගය අගුලු හරින්න"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"මෙම දුරකථනයෙහි වාදනය වේ"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"මෙම ටැබ්ලටයේ වාදනය වේ"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"බලය ක්‍රියාවිරහිත වූ විට පවා ඔබට මගේ උපාංගය සෙවීම මගින් මෙම දුරකථනය සොයාගත හැක"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"බලය ක්‍රියාවිරහිත වූ විට පවා ඔබට මගේ උපාංගය සෙවීම මගින් මෙම ටැබ්ලටය සොයාගත හැක"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sk/strings.xml b/packages/SystemUI/res-product/values-sk/strings.xml
index fbf5ee7..29efb24 100644
--- a/packages/SystemUI/res-product/values-sk/strings.xml
+++ b/packages/SystemUI/res-product/values-sk/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Ak chcete zobraziť ďalšie možnosti, odomknite zariadenie"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Prehráva sa v tomto telefóne"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Prehráva sa v tomto tablete"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Pomocou funkcie Nájdi moje zariadenie môžete zistiť polohu tohto telefónu, aj keď je vypnutý"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Pomocou funkcie Nájdi moje zariadenie môžete zistiť polohu tohto tabletu, aj keď je vypnutý"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sl/strings.xml b/packages/SystemUI/res-product/values-sl/strings.xml
index 04c7bc7..b4fff52 100644
--- a/packages/SystemUI/res-product/values-sl/strings.xml
+++ b/packages/SystemUI/res-product/values-sl/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Za več možnosti odklenite napravo"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Predvajanje v tem telefonu"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Predvajanje v tem tabličnem računalniku"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"S storitvijo Poišči mojo napravo lahko ta telefon poiščete, tudi če je izklopljen"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"S storitvijo Poišči mojo napravo lahko ta tablični računalnik poiščete, tudi če je izklopljen"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sq/strings.xml b/packages/SystemUI/res-product/values-sq/strings.xml
index c0e93c4..1a88b1f 100644
--- a/packages/SystemUI/res-product/values-sq/strings.xml
+++ b/packages/SystemUI/res-product/values-sq/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Shkyçe pajisjen për më shumë opsione"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Po luhet në këtë telefon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Po luhet në këtë tablet"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Mund ta gjesh këtë telefon me \"Gjej pajisjen time\" edhe kur është i fikur"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Mund ta gjesh këtë tablet me \"Gjej pajisjen time\" edhe kur është i fikur"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sr/strings.xml b/packages/SystemUI/res-product/values-sr/strings.xml
index 76cd9ed..72c594d 100644
--- a/packages/SystemUI/res-product/values-sr/strings.xml
+++ b/packages/SystemUI/res-product/values-sr/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Откључајте уређај за још опција"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Пушта се на овом телефону"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Пушта се на овом таблету"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Можете да лоцирате овај телефон помоћу услуге Пронађи мој уређај чак и када је искључен"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Можете да лоцирате овај таблет помоћу услуге Пронађи мој уређај чак и када је искључен"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sv/strings.xml b/packages/SystemUI/res-product/values-sv/strings.xml
index bb97e5c..ce0a2dd 100644
--- a/packages/SystemUI/res-product/values-sv/strings.xml
+++ b/packages/SystemUI/res-product/values-sv/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Lås upp enheten för fler alternativ"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Spelas upp på denna telefon"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Spelas upp på denna surfplatta"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Du kan hitta den här telefonen med Hitta min enhet även när den är avstängd"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Du kan hitta den här surfplattan med Hitta min enhet även när den är avstängd"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-sw/strings.xml b/packages/SystemUI/res-product/values-sw/strings.xml
index 44e95de..1315d2c 100644
--- a/packages/SystemUI/res-product/values-sw/strings.xml
+++ b/packages/SystemUI/res-product/values-sw/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Fungua kifaa chako ili upate chaguo zaidi"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Inacheza kwenye simu hii"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Inacheza kwenye kompyuta hii kibao"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Unaweza kutambua mahali ilipo simu hii ukitumia programu ya Tafuta Kifaa Changu hata kama simu imezimwa"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Unaweza kutambua mahali kilipo kishikwambi hiki ukitumia programu ya Tafuta Kifaa Changu hata kama kimezimwa"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ta/strings.xml b/packages/SystemUI/res-product/values-ta/strings.xml
index 774134e..7c3864d 100644
--- a/packages/SystemUI/res-product/values-ta/strings.xml
+++ b/packages/SystemUI/res-product/values-ta/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"மேலும் விருப்பங்களுக்குச் சாதனத்தை அன்லாக் செய்யவும்"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"இந்த மொபைலில் பிளே ஆகிறது"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"இந்த டேப்லெட்டில் பிளே ஆகிறது"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"இந்த மொபைல் பவர் ஆஃப் செய்யப்பட்டிருக்கும்போதும் Find My Device மூலம் இதன் இருப்பிடத்தைக் கண்டறியலாம்"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"இந்த டேப்லெட் பவர் ஆஃப் செய்யப்பட்டிருக்கும்போதும் Find My Device மூலம் இதன் இருப்பிடத்தைக் கண்டறியலாம்"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-te/strings.xml b/packages/SystemUI/res-product/values-te/strings.xml
index 357b274..69071e0 100644
--- a/packages/SystemUI/res-product/values-te/strings.xml
+++ b/packages/SystemUI/res-product/values-te/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"మరిన్ని ఆప్షన్‌ల కోసం మీ పరికరాన్ని అన్‌లాక్ చేయండి"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"ఈ ఫోన్‌లో ప్లే అవుతోంది"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"ఈ టాబ్లెట్‌లో ప్లే అవుతోంది"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"పవర్ ఆఫ్‌లో ఉన్నప్పుడు కూడా మీరు Find My Deviceతో ఈ ఫోన్‌ను గుర్తించవచ్చు"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"పవర్ ఆఫ్‌లో ఉన్నప్పుడు కూడా మీరు Find My Deviceతో ఈ టాబ్లెట్‌ను గుర్తించవచ్చు"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-th/strings.xml b/packages/SystemUI/res-product/values-th/strings.xml
index ae1f3ed..5798d95 100644
--- a/packages/SystemUI/res-product/values-th/strings.xml
+++ b/packages/SystemUI/res-product/values-th/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"ปลดล็อกอุปกรณ์เพื่อดูตัวเลือกเพิ่มเติม"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"กำลังเล่นในโทรศัพท์เครื่องนี้"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"กำลังเล่นในแท็บเล็ตเครื่องนี้"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"คุณจะหาตำแหน่งของโทรศัพท์นี้ได้ด้วยแอปหาอุปกรณ์ของฉันแม้จะปิดเครื่องอยู่ก็ตาม"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"คุณจะหาตำแหน่งของแท็บเล็ตนี้ได้ด้วยแอปหาอุปกรณ์ของฉันแม้จะปิดเครื่องอยู่ก็ตาม"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-tl/strings.xml b/packages/SystemUI/res-product/values-tl/strings.xml
index 74f30ae..09a58c8 100644
--- a/packages/SystemUI/res-product/values-tl/strings.xml
+++ b/packages/SystemUI/res-product/values-tl/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"I-unlock ang iyong device para sa higit pang opsyon"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Nagpe-play sa teleponong ito"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Nagpe-play sa tablet na ito"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Puwede mong hanapin ang teleponong ito gamit ang Hanapin ang Aking Device kahit naka-off ito"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Puwede mong hanapin ang tablet na ito gamit ang Hanapin ang Aking Device kahit naka-off ito"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-tr/strings.xml b/packages/SystemUI/res-product/values-tr/strings.xml
index 68183e4..25d75f4 100644
--- a/packages/SystemUI/res-product/values-tr/strings.xml
+++ b/packages/SystemUI/res-product/values-tr/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Diğer seçenekler için cihazınızın kilidini açın"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Bu telefonda oynatılıyor"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Bu tablette oynatılıyor"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Bu telefonu kapalıyken bile Cihazımı Bul işleviyle bulabilirsiniz."</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Bu tableti kapalıyken bile Cihazımı Bul işleviyle bulabilirsiniz."</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-uk/strings.xml b/packages/SystemUI/res-product/values-uk/strings.xml
index 24d5cc9..4a29b90 100644
--- a/packages/SystemUI/res-product/values-uk/strings.xml
+++ b/packages/SystemUI/res-product/values-uk/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Розблокуйте пристрій, щоб переглянути інші параметри"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Відтворюється на цьому телефоні"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Відтворюється на цьому планшеті"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Ви зможете визначити місцеположення цього телефона, навіть коли його вимкнено, за допомогою сервісу Знайти пристрій"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Ви зможете визначити місцеположення цього планшета, навіть коли його вимкнено, за допомогою сервісу Знайти пристрій"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-ur/strings.xml b/packages/SystemUI/res-product/values-ur/strings.xml
index 98fe163..36a2e53 100644
--- a/packages/SystemUI/res-product/values-ur/strings.xml
+++ b/packages/SystemUI/res-product/values-ur/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"مزید اختیارات کے لیے اپنا آلہ غیر مقفل کریں"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"اس فون پر چل رہا ہے"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"اس ٹیبلیٹ پر چل رہا ہے"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"پاور آف ہونے پر بھی آپ میرا آلہ ڈھونڈیں کے ساتھ اس فون کو تلاش کر سکتے ہیں"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"پاور آف ہونے پر بھی آپ میرا آلہ ڈھونڈیں کے ساتھ اس ٹیبلیٹ کو تلاش کر سکتے ہیں"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-uz/strings.xml b/packages/SystemUI/res-product/values-uz/strings.xml
index 38f9ebb..21b5d4c 100644
--- a/packages/SystemUI/res-product/values-uz/strings.xml
+++ b/packages/SystemUI/res-product/values-uz/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Boshqa parametrlar uchun qurilmangiz qulfini oching"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Bu telefonda ijro qilinmoqda"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Bu planshetda ijro etilmoqda"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Oʻchiq boʻlsa ham “Qurilmani top” funksiyasi yordamida bu telefonni topish mumkin"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Oʻchiq boʻlsa ham “Qurilmani top” funksiyasi yordamida bu planshetni topish mumkin"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-vi/strings.xml b/packages/SystemUI/res-product/values-vi/strings.xml
index fb3f862..ca02f0c 100644
--- a/packages/SystemUI/res-product/values-vi/strings.xml
+++ b/packages/SystemUI/res-product/values-vi/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Mở khóa thiết bị của bạn để xem thêm tùy chọn"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Đang phát trên điện thoại này"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Đang phát trên máy tính bảng này"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Bạn có thể định vị chiếc điện thoại này bằng ứng dụng Tìm thiết bị của tôi ngay cả khi điện thoại tắt nguồn"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Bạn có thể định vị chiếc máy tính bảng này bằng ứng dụng Tìm thiết bị của tôi ngay cả khi máy tính bảng tắt nguồn"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-zh-rCN/strings.xml b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
index de308ddb..570afea 100644
--- a/packages/SystemUI/res-product/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rCN/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解锁设备即可查看更多选项"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"正在此手机上播放"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"正在此平板电脑上播放"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"即使这部手机已关机,您也可以通过“查找我的设备”确定其位置"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"即使这部平板电脑已关机,您也可以通过“查找我的设备”确定其位置"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-zh-rHK/strings.xml b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
index 6bcb048..c3dcc9f 100644
--- a/packages/SystemUI/res-product/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rHK/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置以存取更多選項"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"正在此手機上播放"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"正在此平板電腦上播放"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"即使手機關機,仍可透過「尋找我的裝置」尋找此手機"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"即使平板電腦關機,仍可透過「尋找我的裝置」尋找此平板電腦"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-zh-rTW/strings.xml b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
index f407803..9cbc1a6 100644
--- a/packages/SystemUI/res-product/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-product/values-zh-rTW/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"解鎖裝置可查看更多選項"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"正在這支手機上播放"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"正在這台平板電腦上播放"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"即使這支手機關機,仍可透過「尋找我的裝置」找出所在位置"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"即使這台平板電腦關機,還是可以透過「尋找我的裝置」找出所在位置"</string>
 </resources>
diff --git a/packages/SystemUI/res-product/values-zu/strings.xml b/packages/SystemUI/res-product/values-zu/strings.xml
index 6374f1f..9f45199 100644
--- a/packages/SystemUI/res-product/values-zu/strings.xml
+++ b/packages/SystemUI/res-product/values-zu/strings.xml
@@ -66,4 +66,6 @@
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Vula idivayisi yakho ukuthola okunye okungakhethwa"</string>
     <string name="media_transfer_playing_this_device" product="default" msgid="5795784619523545556">"Okudlala kule foni"</string>
     <string name="media_transfer_playing_this_device" product="tablet" msgid="222514408550408633">"Okudlala kule thebhulethi"</string>
+    <string name="finder_active" product="default" msgid="2734050945122991747">"Ungathola le foni ngokuthi Thola Idivayisi Yami noma ivaliwe"</string>
+    <string name="finder_active" product="tablet" msgid="8045583079989970505">"Ungathola le thebhulethi ngokuthi Thola Idivayisi Yami noma ivaliwe"</string>
 </resources>
diff --git a/packages/SystemUI/res/color/slider_inactive_track_color.xml b/packages/SystemUI/res/color/slider_inactive_track_color.xml
deleted file mode 100644
index 7980f80..0000000
--- a/packages/SystemUI/res/color/slider_inactive_track_color.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright (C) 2024 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorPrimary" />
-</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/slider_thumb_color.xml b/packages/SystemUI/res/color/slider_thumb_color.xml
deleted file mode 100644
index 8a98902..0000000
--- a/packages/SystemUI/res/color/slider_thumb_color.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  ~ Copyright (C) 2024 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" android:state_enabled="false" />
-    <item android:color="@androidprv:color/materialColorPrimary" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/audio_bars_idle.xml b/packages/SystemUI/res/drawable/audio_bars_idle.xml
new file mode 100644
index 0000000..92a2475
--- /dev/null
+++ b/packages/SystemUI/res/drawable/audio_bars_idle.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="168dp"
+    android:height="168dp"
+    android:viewportWidth="168"
+    android:viewportHeight="168">
+    <group android:name="_R_G">
+        <group
+            android:name="_R_G_L_2_G"
+            android:translateX="121.161"
+            android:translateY="83.911">
+            <path
+                android:name="_R_G_L_2_G_D_0_P_0"
+                android:fillAlpha="1"
+                android:fillColor="#ffffff"
+                android:fillType="nonZero"
+                android:pathData=" M-37.16 -5.87 C-33.94,-5.87 -31.32,-3.32 -31.2,-0.13 C-31.2,-0.06 -31.2,0.02 -31.2,0.09 C-31.2,0.16 -31.2,0.23 -31.2,0.29 C-31.31,3.49 -33.94,6.05 -37.16,6.05 C-40.39,6.05 -43.01,3.49 -43.12,0.29 C-43.12,0.23 -43.12,0.16 -43.12,0.09 C-43.12,0.01 -43.12,-0.07 -43.12,-0.15 C-42.99,-3.33 -40.37,-5.87 -37.16,-5.87c " />
+        </group>
+        <group
+            android:name="_R_G_L_1_G"
+            android:translateX="102.911"
+            android:translateY="83.911">
+            <path
+                android:name="_R_G_L_1_G_D_0_P_0"
+                android:fillAlpha="1"
+                android:fillColor="#ffffff"
+                android:fillType="nonZero"
+                android:pathData=" M-37.16 -5.87 C-33.94,-5.87 -31.32,-3.32 -31.2,-0.13 C-31.2,-0.06 -31.2,0.02 -31.2,0.09 C-31.2,0.16 -31.2,0.23 -31.2,0.29 C-31.31,3.49 -33.94,6.05 -37.16,6.05 C-40.39,6.05 -43.01,3.49 -43.12,0.29 C-43.12,0.23 -43.12,0.16 -43.12,0.09 C-43.12,0.01 -43.12,-0.07 -43.12,-0.15 C-42.99,-3.33 -40.37,-5.87 -37.16,-5.87c " />
+        </group>
+        <group
+            android:name="_R_G_L_0_G"
+            android:translateX="139.661"
+            android:translateY="83.911">
+            <path
+                android:name="_R_G_L_0_G_D_0_P_0"
+                android:fillAlpha="1"
+                android:fillColor="#ffffff"
+                android:fillType="nonZero"
+                android:pathData=" M-37.16 -5.87 C-33.94,-5.87 -31.32,-3.32 -31.2,-0.13 C-31.2,-0.06 -31.2,0.02 -31.2,0.09 C-31.2,0.16 -31.2,0.23 -31.2,0.29 C-31.31,3.49 -33.94,6.05 -37.16,6.05 C-40.39,6.05 -43.01,3.49 -43.12,0.29 C-43.12,0.23 -43.12,0.16 -43.12,0.09 C-43.12,0.01 -43.12,-0.07 -43.12,-0.15 C-42.99,-3.33 -40.37,-5.87 -37.16,-5.87c " />
+        </group>
+    </group>
+    <group android:name="time_group" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/hearing_devices_spinner_background.xml b/packages/SystemUI/res/drawable/hearing_devices_spinner_background.xml
index dfefb9d..4b7be35 100644
--- a/packages/SystemUI/res/drawable/hearing_devices_spinner_background.xml
+++ b/packages/SystemUI/res/drawable/hearing_devices_spinner_background.xml
@@ -27,18 +27,7 @@
             <solid android:color="@android:color/transparent"/>
         </shape>
     </item>
-    <item
-        android:end="20dp"
-        android:gravity="end|center_vertical">
-        <vector
-            android:width="@dimen/hearing_devices_preset_spinner_icon_size"
-            android:height="@dimen/hearing_devices_preset_spinner_icon_size"
-            android:viewportWidth="24"
-            android:viewportHeight="24"
-            android:tint="?androidprv:attr/colorControlNormal">
-            <path
-                android:fillColor="#FF000000"
-                android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
-        </vector>
-    </item>
+    <item android:end="20dp"
+        android:gravity="end|center_vertical"
+        android:drawable="@drawable/ic_hearing_device_expand" />
 </layer-list>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_hearing_device_expand.xml b/packages/SystemUI/res/drawable/ic_hearing_device_expand.xml
new file mode 100644
index 0000000..fdfe713
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_hearing_device_expand.xml
@@ -0,0 +1,27 @@
+<!--
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="@androidprv:color/materialColorOnSurface">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
deleted file mode 100644
index 9ce030e..0000000
--- a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?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.
-  -->
-
-<!-- LinearLayout -->
-<com.android.systemui.statusbar.policy.KeyguardUserDetailItemView
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:sysui="http://schemas.android.com/apk/res-auto"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="8dp"
-        android:layout_marginEnd="32dp"
-        android:gravity="end|center_vertical"
-        android:clickable="true"
-        android:background="@drawable/kg_user_switcher_rounded_bg"
-        sysui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
-        sysui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher">
-    <TextView android:id="@+id/user_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="25dp"
-            android:layout_marginEnd="12dp"
-            />
-    <com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
-            android:layout_width="@dimen/kg_framed_avatar_size"
-            android:layout_height="@dimen/kg_framed_avatar_size"
-            android:contentDescription="@null"
-            sysui:badgeDiameter="18dp"
-            sysui:badgeMargin="1dp" />
-</com.android.systemui.statusbar.policy.KeyguardUserDetailItemView>
diff --git a/packages/SystemUI/res/layout/hearing_device_ambient_volume_layout.xml b/packages/SystemUI/res/layout/hearing_device_ambient_volume_layout.xml
new file mode 100644
index 0000000..fd409a5
--- /dev/null
+++ b/packages/SystemUI/res/layout/hearing_device_ambient_volume_layout.xml
@@ -0,0 +1,67 @@
+<!--
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/ambient_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="@dimen/bluetooth_dialog_layout_margin"
+        android:layout_marginEnd="@dimen/bluetooth_dialog_layout_margin"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+id/ambient_volume_icon"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="12dp"
+            android:contentDescription="@string/hearing_devices_ambient_unmute"
+            android:src="@drawable/ic_ambient_volume"
+            android:tint="@androidprv:color/materialColorOnSurface" />
+        <TextView
+            android:id="@+id/ambient_title"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingStart="10dp"
+            android:text="@string/hearing_devices_ambient_label"
+            android:textAppearance="@style/TextAppearance.Dialog.Title"
+            android:textDirection="locale"
+            android:textSize="16sp"
+            android:gravity="center_vertical"
+            android:fontFamily="@*android:string/config_headlineFontFamilyMedium" />
+        <ImageView
+            android:id="@+id/ambient_expand_icon"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:padding="10dp"
+            android:contentDescription="@string/hearing_devices_ambient_expand_controls"
+            android:src="@drawable/ic_hearing_device_expand"
+            android:tint="@androidprv:color/materialColorOnSurface" />
+    </LinearLayout>
+    <LinearLayout
+        android:id="@+id/ambient_control_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/hearing_device_ambient_volume_slider.xml b/packages/SystemUI/res/layout/hearing_device_ambient_volume_slider.xml
new file mode 100644
index 0000000..44ada89
--- /dev/null
+++ b/packages/SystemUI/res/layout/hearing_device_ambient_volume_slider.xml
@@ -0,0 +1,46 @@
+<!--
+    Copyright (C) 2024 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="@dimen/bluetooth_dialog_layout_margin"
+    android:layout_marginEnd="@dimen/bluetooth_dialog_layout_margin"
+    android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/ambient_volume_slider_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:paddingStart="@dimen/hearing_devices_small_title_padding_horizontal"
+        android:textAppearance="@style/TextAppearance.Dialog.Title"
+        android:textDirection="locale"
+        android:textSize="14sp"
+        android:labelFor="@+id/ambient_volume_slider"
+        android:gravity="center_vertical" />
+    <com.google.android.material.slider.Slider
+        style="@style/SystemUI.Material3.Slider"
+        android:id="@+id/ambient_volume_slider"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/bluetooth_dialog_device_height"
+        android:layout_gravity="center_vertical"
+        android:theme="@style/Theme.Material3.DayNight"
+        app:labelBehavior="gone" />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml b/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
index bf04a6f..949a6ab 100644
--- a/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
+++ b/packages/SystemUI/res/layout/hearing_devices_tile_dialog.xml
@@ -85,13 +85,22 @@
             android:longClickable="false"/>
     </LinearLayout>
 
+    <com.android.systemui.accessibility.hearingaid.AmbientVolumeLayout
+        android:id="@+id/ambient_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/preset_layout"
+        android:layout_marginTop="@dimen/hearing_devices_layout_margin" />
+
     <LinearLayout
         android:id="@+id/tools_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/preset_layout"
+        app:layout_constraintTop_toBottomOf="@id/ambient_layout"
         android:layout_marginTop="@dimen/hearing_devices_layout_margin"
         android:orientation="vertical">
         <TextView
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher.xml b/packages/SystemUI/res/layout/keyguard_user_switcher.xml
deleted file mode 100644
index 7aafd89..0000000
--- a/packages/SystemUI/res/layout/keyguard_user_switcher.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-<!-- This is a view that shows a user switcher in Keyguard. -->
-<com.android.systemui.statusbar.policy.KeyguardUserSwitcherView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/keyguard_user_switcher_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_gravity="end">
-
-    <com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView
-        android:id="@+id/keyguard_user_switcher_list"
-        android:orientation="vertical"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:layout_gravity="top|end"
-        android:gravity="end" />
-
-</com.android.systemui.statusbar.policy.KeyguardUserSwitcherView>
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
deleted file mode 100644
index e39f1a9..0000000
--- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  ~ Copyright (C) 2014 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License
-  -->
-
-<!-- LinearLayout -->
-<com.android.systemui.statusbar.policy.KeyguardUserDetailItemView
-        android:id="@+id/user_item"
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:systemui="http://schemas.android.com/apk/res-auto"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="8dp"
-        android:layout_marginEnd="8dp"
-        android:gravity="end|center_vertical"
-        android:clickable="true"
-        android:background="@drawable/kg_user_switcher_rounded_bg"
-        systemui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
-        systemui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher">
-    <TextView
-        android:id="@+id/user_name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="20dp"
-        android:layout_marginEnd="16dp" />
-    <com.android.systemui.statusbar.phone.UserAvatarView
-        android:id="@+id/user_picture"
-        android:layout_width="@dimen/kg_framed_avatar_size"
-        android:layout_height="@dimen/kg_framed_avatar_size"
-        systemui:avatarPadding="0dp"
-        systemui:badgeDiameter="18dp"
-        systemui:badgeMargin="1dp"
-        systemui:frameWidth="0dp"
-        systemui:framePadding="0dp"
-        systemui:frameColor="@color/kg_user_avatar_frame" />
-</com.android.systemui.statusbar.policy.KeyguardUserDetailItemView>
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index 9c1dc64..6f8b4cd 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -120,36 +120,6 @@
     </LinearLayout>
 
     <LinearLayout
-        android:id="@+id/cast_app_section"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="20dp"
-        android:layout_marginStart="@dimen/dialog_side_padding"
-        android:layout_marginEnd="@dimen/dialog_side_padding"
-        android:layout_marginBottom="@dimen/dialog_bottom_padding"
-        android:orientation="vertical"
-        android:visibility="gone">
-        <TextView
-            android:id="@+id/launch_app_title"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical|start"
-            android:ellipsize="end"
-            android:textColor="?android:attr/textColorPrimary"
-            android:text="@string/media_output_dialog_launch_app_text"
-            android:maxLines="1"
-            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-            android:textSize="16sp"/>
-
-        <Button
-            android:id="@+id/launch_app_button"
-            style="@style/Widget.Dialog.Button.BorderButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:drawablePadding="5dp"/>
-    </LinearLayout>
-
-    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="4dp"
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
similarity index 82%
rename from packages/SystemUI/res/layout/ongoing_activity_chip.xml
rename to packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
index 7745af9..6f42286 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
@@ -13,17 +13,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<!-- Have the wrapper frame layout match the parent height so that we get a larger touch area for
-     the chip. -->
-<FrameLayout
+
+<merge
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="match_parent"
-    android:layout_gravity="center_vertical|start"
-    android:layout_marginStart="5dp"
->
-    <!-- TODO(b/332662551): Update this content description when this supports more than just
-         phone calls. -->
+    >
+
     <com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
         android:id="@+id/ongoing_activity_chip_background"
         android:layout_width="wrap_content"
@@ -39,7 +33,7 @@
         <ImageView
             android:src="@*android:drawable/ic_phone"
             android:id="@+id/ongoing_activity_chip_icon"
-            android:contentDescription="@string/ongoing_phone_call_content_description"
+            android:contentDescription="@string/ongoing_call_content_description"
             android:layout_width="@dimen/ongoing_activity_chip_icon_size"
             android:layout_height="@dimen/ongoing_activity_chip_icon_size"
             android:tint="?android:attr/colorPrimary"
@@ -58,18 +52,18 @@
         />
 
         <!-- Shows generic text. -->
-        <TextView
+        <com.android.systemui.statusbar.chips.ui.view.ChipTextView
             android:id="@+id/ongoing_activity_chip_text"
             style="@style/StatusBar.Chip.Text.LimitedWidth"
             android:visibility="gone"
             />
 
         <!-- Shows a time delta in short form, like "15min" or "1hr". -->
-        <android.widget.DateTimeView
+        <com.android.systemui.statusbar.chips.ui.view.ChipDateTimeView
             android:id="@+id/ongoing_activity_chip_short_time_delta"
             style="@style/StatusBar.Chip.Text.LimitedWidth"
             android:visibility="gone"
             />
 
     </com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer>
-</FrameLayout>
+</merge>
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml
similarity index 66%
copy from packages/SystemUI/res/color/slider_active_track_color.xml
copy to packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml
index 8ba5e49..114fe6c 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_primary.xml
@@ -13,7 +13,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+
+<FrameLayout
+    style="@style/StatusBar.Chip.RootView">
+
+    <include layout="@layout/ongoing_activity_chip_content" />
+
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/color/slider_active_track_color.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml
similarity index 66%
rename from packages/SystemUI/res/color/slider_active_track_color.xml
rename to packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml
index 8ba5e49..81a7822 100644
--- a/packages/SystemUI/res/color/slider_active_track_color.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_secondary.xml
@@ -13,7 +13,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item android:color="@androidprv:color/materialColorPrimary" android:state_enabled="true" />
-    <item android:color="@androidprv:color/materialColorSurfaceContainerHighest" />
-</selector>
\ No newline at end of file
+
+<com.android.systemui.statusbar.chips.ui.view.SecondaryOngoingActivityChip
+    style="@style/StatusBar.Chip.RootView">
+
+    <include layout="@layout/ongoing_activity_chip_content" />
+
+</com.android.systemui.statusbar.chips.ui.view.SecondaryOngoingActivityChip>
+
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index 78d1ab2..9da373b 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -51,6 +51,7 @@
             android:layout_height="@dimen/screenrecord_spinner_height"
             android:layout_marginTop="@dimen/screenrecord_spinner_margin"
             android:layout_marginBottom="@dimen/screenrecord_spinner_margin"
+            android:dropDownWidth="match_parent"
             android:gravity="center_vertical"
             android:background="@drawable/screenshare_options_spinner_background"
             android:popupBackground="@drawable/screenrecord_options_spinner_popup_background"/>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 1f4dea9..e4da472 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -103,10 +103,10 @@
                         android:gravity="center_vertical|start"
                     />
 
-                    <include layout="@layout/ongoing_activity_chip"
+                    <include layout="@layout/ongoing_activity_chip_primary"
                         android:id="@+id/ongoing_activity_chip_primary"/>
 
-                    <include layout="@layout/ongoing_activity_chip"
+                    <include layout="@layout/ongoing_activity_chip_secondary"
                         android:id="@+id/ongoing_activity_chip_secondary"
                         android:visibility="gone"/>
 
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 77fbb64..b106ad5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -31,12 +31,6 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
-    <ViewStub
-        android:id="@+id/keyguard_qs_user_switch_stub"
-        android:layout="@layout/keyguard_qs_user_switch"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
     <include layout="@layout/status_bar_expanded_plugin_frame"/>
 
     <com.android.systemui.shade.NotificationsQuickSettingsContainer
@@ -47,10 +41,6 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <include
-            layout="@layout/keyguard_status_view"
-            android:visibility="gone"/>
-
         <include layout="@layout/dock_info_overlay"/>
 
         <FrameLayout
@@ -120,12 +110,6 @@
         />
     </com.android.systemui.shade.NotificationsQuickSettingsContainer>
 
-    <ViewStub
-        android:id="@+id/keyguard_user_switcher_stub"
-        android:layout="@layout/keyguard_user_switcher"
-        android:layout_height="match_parent"
-        android:layout_width="match_parent" />
-
     <include layout="@layout/dock_info_bottom_area_overlay" />
 
     <include
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index a3bad8f..bad5711 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -56,8 +56,8 @@
         android:layout_marginTop="@dimen/volume_dialog_components_spacing"
         android:background="@drawable/ripple_drawable_20dp"
         android:contentDescription="@string/accessibility_volume_settings"
+        android:scaleType="centerInside"
         android:soundEffectsEnabled="false"
-        android:src="@drawable/horizontal_ellipsis"
         android:tint="@androidprv:color/materialColorPrimary"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="@id/volume_dialog_main_slider_container"
@@ -71,6 +71,9 @@
         android:layout_height="0dp"
         android:layout_marginTop="@dimen/volume_dialog_floating_sliders_vertical_padding_negative"
         android:layout_marginBottom="@dimen/volume_dialog_floating_sliders_vertical_padding_negative"
+        android:clipChildren="false"
+        android:clipToOutline="false"
+        android:clipToPadding="false"
         android:divider="@drawable/volume_dialog_floating_sliders_spacer"
         android:gravity="bottom"
         android:orientation="horizontal"
diff --git a/packages/SystemUI/res/layout/volume_dialog_slider.xml b/packages/SystemUI/res/layout/volume_dialog_slider.xml
index 9ac456c..0acf410 100644
--- a/packages/SystemUI/res/layout/volume_dialog_slider.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_slider.xml
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
@@ -24,11 +23,6 @@
         android:layout_width="@dimen/volume_dialog_slider_width"
         android:layout_height="@dimen/volume_dialog_slider_height"
         android:layout_gravity="center"
-        android:theme="@style/Theme.Material3.Light"
         android:orientation="vertical"
-        app:thumbHeight="52dp"
-        app:trackCornerSize="12dp"
-        app:trackHeight="40dp"
-        app:trackStopIndicatorSize="6dp"
-        app:trackInsideCornerSize="2dp" />
+        android:theme="@style/Theme.Material3.DayNight" />
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
index d850bbe..cd8f18f 100644
--- a/packages/SystemUI/res/layout/volume_ringer_drawer.xml
+++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml
@@ -23,7 +23,6 @@
     android:clipToPadding="false"
     android:gravity="center"
     android:layoutDirection="ltr"
-    android:orientation="vertical"
     app:layoutDescription="@xml/volume_dialog_ringer_drawer_motion_scene">
 
     <!-- add ringer buttons here -->
diff --git a/packages/SystemUI/res/raw/audio_bars_in.json b/packages/SystemUI/res/raw/audio_bars_in.json
new file mode 100644
index 0000000..c90a59c
--- /dev/null
+++ b/packages/SystemUI/res/raw/audio_bars_in.json
@@ -0,0 +1 @@
+{"v":"5.7.13","fr":60,"ip":0,"op":18,"w":168,"h":168,"nm":"audio_bars_in","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[120.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":17,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-22.725],[5.957,-16.983],[5.961,0],[5.958,17.391],[0,23.149],[-5.958,17.39],[-5.961,0],[-5.957,-16.998]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[102.5,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":17,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-38.225],[5.957,-32.483],[5.961,0],[5.958,32.016],[0,37.774],[-5.958,32.015],[-5.961,0],[-5.957,-32.498]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[65.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":17,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-25.1],[5.957,-19.358],[5.961,0],[5.958,19.516],[0,25.274],[-5.958,19.515],[-5.961,0],[-5.957,-19.373]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":17,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-18.6],[5.957,-12.858],[5.961,0],[5.958,13.141],[0,18.899],[-5.958,13.14],[-5.961,0],[-5.957,-12.873]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[47.25,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":17,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-13.475],[5.957,-7.733],[5.961,0],[5.958,6.766],[0,12.524],[-5.958,6.765],[-5.961,0],[-5.957,-7.748]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":5,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/audio_bars_out.json b/packages/SystemUI/res/raw/audio_bars_out.json
new file mode 100644
index 0000000..5eab65e0
--- /dev/null
+++ b/packages/SystemUI/res/raw/audio_bars_out.json
@@ -0,0 +1 @@
+{"v":"5.7.13","fr":60,"ip":0,"op":31,"w":168,"h":168,"nm":"audio_bars_out","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":5,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[120.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-22.725],[5.957,-16.983],[5.961,0],[5.958,17.391],[0,23.149],[-5.958,17.39],[-5.961,0],[-5.957,-16.998]],"c":true}]},{"t":30,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":5,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[102.5,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-38.225],[5.957,-32.483],[5.961,0],[5.958,32.016],[0,37.774],[-5.958,32.015],[-5.961,0],[-5.957,-32.498]],"c":true}]},{"t":30,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[65.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-25.1],[5.957,-19.358],[5.961,0],[5.958,19.516],[0,25.274],[-5.958,19.515],[-5.961,0],[-5.957,-19.373]],"c":true}]},{"t":30,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-18.6],[5.957,-12.858],[5.961,0],[5.958,13.141],[0,18.899],[-5.958,13.14],[-5.961,0],[-5.957,-12.873]],"c":true}]},{"t":30,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":5,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[47.25,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-13.475],[5.957,-7.733],[5.961,0],[5.958,6.766],[0,12.524],[-5.958,6.765],[-5.961,0],[-5.957,-7.748]],"c":true}]},{"t":30,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":5,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/audio_bars_playing.json b/packages/SystemUI/res/raw/audio_bars_playing.json
new file mode 100644
index 0000000..6ee8e19
--- /dev/null
+++ b/packages/SystemUI/res/raw/audio_bars_playing.json
@@ -0,0 +1 @@
+{"v":"5.7.13","fr":60,"ip":0,"op":121,"w":168,"h":168,"nm":"audio_bars_playing","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[120.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-22.725],[5.957,-16.983],[5.961,0],[5.958,17.391],[0,23.149],[-5.958,17.39],[-5.961,0],[-5.957,-16.998]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":38,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[-0.016,-14.1],[5.941,-8.358],[5.961,0],[5.958,8.516],[0,14.274],[-5.958,8.515],[-5.961,0],[-5.972,-8.373]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":70,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-22.725],[5.957,-16.983],[5.961,0],[5.958,17.391],[0,23.149],[-5.958,17.39],[-5.961,0],[-5.957,-16.998]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":102,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[-0.016,-14.1],[5.941,-8.358],[5.961,0],[5.958,8.516],[0,14.274],[-5.958,8.515],[-5.961,0],[-5.972,-8.373]],"c":true}]},{"t":120,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-22.725],[5.957,-16.983],[5.961,0],[5.958,17.391],[0,23.149],[-5.958,17.39],[-5.961,0],[-5.957,-16.998]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":121,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[102.5,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-38.225],[5.957,-32.483],[5.961,0],[5.958,32.016],[0,37.774],[-5.958,32.015],[-5.961,0],[-5.957,-32.498]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":32,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-19.1],[5.957,-13.358],[5.961,0],[5.958,13.641],[0,19.399],[-5.958,13.64],[-5.961,0],[-5.957,-13.373]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":65,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-38.225],[5.957,-32.483],[5.961,0],[5.958,32.016],[0,37.774],[-5.958,32.015],[-5.961,0],[-5.957,-32.498]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":97,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-19.1],[5.957,-13.358],[5.961,0],[5.958,13.641],[0,19.399],[-5.958,13.64],[-5.961,0],[-5.957,-13.373]],"c":true}]},{"t":120,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-38.225],[5.957,-32.483],[5.961,0],[5.958,32.016],[0,37.774],[-5.958,32.015],[-5.961,0],[-5.957,-32.498]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":121,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[65.75,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-25.1],[5.957,-19.358],[5.961,0],[5.958,19.516],[0,25.274],[-5.958,19.515],[-5.961,0],[-5.957,-19.373]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":29,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-15.85],[5.957,-10.108],[5.961,0],[5.958,10.516],[0,16.274],[-5.958,10.515],[-5.961,0],[-5.957,-10.123]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":59,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-25.1],[5.957,-19.358],[5.961,0],[5.958,19.516],[0,25.274],[-5.958,19.515],[-5.961,0],[-5.957,-19.373]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":91,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-15.85],[5.957,-10.108],[5.961,0],[5.958,10.516],[0,16.274],[-5.958,10.515],[-5.961,0],[-5.957,-10.123]],"c":true}]},{"t":120,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-25.1],[5.957,-19.358],[5.961,0],[5.958,19.516],[0,25.274],[-5.958,19.515],[-5.961,0],[-5.957,-19.373]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":121,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[84,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-18.6],[5.957,-12.858],[5.961,0],[5.958,13.141],[0,18.899],[-5.958,13.14],[-5.961,0],[-5.957,-12.873]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-9.225],[5.957,-3.483],[5.961,0],[5.958,3.766],[0,9.524],[-5.958,3.765],[-5.961,0],[-5.957,-3.498]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":54,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-18.6],[5.957,-12.858],[5.961,0],[5.958,13.141],[0,18.899],[-5.958,13.14],[-5.961,0],[-5.957,-12.873]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":86,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-9.225],[5.957,-3.483],[5.961,0],[5.958,3.766],[0,9.524],[-5.958,3.765],[-5.961,0],[-5.957,-3.498]],"c":true}]},{"t":120,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-18.6],[5.957,-12.858],[5.961,0],[5.958,13.141],[0,18.899],[-5.958,13.14],[-5.961,0],[-5.957,-12.873]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":121,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[47.25,84,0],"ix":2,"l":2},"a":{"a":0,"k":[-37.161,0.089,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-13.475],[5.957,-7.733],[5.961,0],[5.958,6.766],[0,12.524],[-5.958,6.765],[-5.961,0],[-5.957,-7.748]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":19,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-13.475],[5.957,-7.733],[5.961,0],[5.958,6.766],[0,12.524],[-5.958,6.765],[-5.961,0],[-5.957,-7.748]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":81,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-5.961],[5.957,-0.219],[5.961,0],[5.958,0.203],[0,5.961],[-5.958,0.203],[-5.961,0],[-5.957,-0.235]],"c":true}]},{"t":120,"s":[{"i":[[-3.214,0],[-0.115,-3.191],[0,-0.073],[0.002,-0.067],[3.224,0],[0.107,3.198],[0,0.068],[-0.003,0.078]],"o":[[3.219,0],[0.003,0.073],[0,0.068],[-0.107,3.198],[-3.224,0],[-0.002,-0.067],[0,-0.079],[0.123,-3.184]],"v":[[0,-13.475],[5.957,-7.733],[5.961,0],[5.958,6.766],[0,12.524],[-5.958,6.765],[-5.961,0],[-5.957,-7.748]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-37.161,0.089],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":121,"st":0,"bm":0}],"markers":[{"tm":60,"cm":"1","dr":0}]}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1d0524a..72b57ca 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Legstukke"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Maak seker dat “Wys legstukke op sluitskerm” in instellings geaktiveer is om die “Legstukke”-kortpad by te voeg."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Instellings"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Wys sluimerskermknoppie"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliet-SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepe of SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"geen sein nie"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"een staaf"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"twee stawe"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"drie stawe"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"vier stawe"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sein is vol"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Word aan die bokant van gesprekskennisgewings en as \'n profielfoto op sluitskerm gewys, verskyn as \'n borrel, onderbreek Moenie Steur Nie"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> steun nie gesprekskenmerke nie"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Verskaf bondelterugvoer"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Hierdie kennisgewings kan nie gewysig word nie."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Oproepkennisgewings kan nie gewysig word nie."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Hierdie groep kennisgewings kan nie hier opgestel word nie"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Sluit skerm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Maak ’n nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Verrigting van veelvuldige take"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Gebruik verdeelde skerm met app aan die regterkant"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Gebruik verdeelde skerm met app aan die linkerkant"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Skakel oor na volskerm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skakel oor na app regs of onder terwyl jy verdeelde skerm gebruik"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skakel oor na app links of bo terwyl jy verdeelde skerm gebruik"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Tydens verdeelde skerm: verplaas ’n app van een skerm na ’n ander"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aan/af-kieslys"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Sluitskerm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Jy kan hierdie foon met Kry My Toestel opspoor selfs wanneer dit afgeskakel is"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Sit tans af …"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Sien versorgingstappe"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sien versorgingstappe"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Gaan na tuisskerm"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Bekyk onlangse apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gaan terug"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swiep links of regs met drie vingers op jou raakpaneel"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Mooi so!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Jy het die Gaan Terug-gebaar voltooi."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gaan na tuisskerm"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swiep op met drie vingers op jou raakpaneel"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Uitstekende werk!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Jy het die Gaan na Tuisskerm-gebaar voltooi"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Bekyk onlangse apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swiep op en hou met drie vingers op jou raakpaneel"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Knap gedaan!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jy het die Bekyk Onlangse Apps-gebaar voltooi."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Bekyk alle apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Druk die handelingsleutel op jou sleutelbord"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Welgedaan!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Jy het die Bekyk Onlangse Apps-gebaar voltooi"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutoriaalanimasie; klik om te onderbreek of hervat om te speel."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Sleutelbordlig"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Vlak %1$d van %2$d"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 687bd08..586c204 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ምግብሮች"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"የ«ምግብሮች» አቋራጭን ለማከል በቅንብሮች ውስጥ «ምግብሮችን በማያ ገፅ ቁልፍ ላይ አሳይ» የሚለው መንቃቱን ያረጋግጡ።"</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ቅንብሮች"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"የገፀ ማያ አሳራፊ አዝራርን አሳይ"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ሳተላይት ኤስኦኤስ"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"የአደጋ ጥሪዎች ወይም ኤስኦኤስ"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>፣ <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>።"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ምንም ምልክት የለም"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"አንድ አሞሌ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ሁለት አሞሌዎች"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"ሦስት አሞሌዎች"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"አራት አሞሌዎች"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ምልክት ሙሉ ነው"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"በውይይት ማሳወቂያዎች አናት ላይ እና በማያ ገፅ መቆለፊያ ላይ እንደ መገለጫ ምስል ይታያል፣ እንደ አረፋ ሆኖ ይታያል፣ አትረብሽን ያቋርጣል"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ቅድሚያ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> የውይይት ባህሪያትን አይደግፍም"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"የቅርቅብ ግብረመልስ አቅርብ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"እነዚህ ማሳወቂያዎች ሊሻሻሉ አይችሉም።"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"የጥሪ ማሳወቂያዎች ሊቀየሩ አይችሉም።"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"የማሳወቂያዎች ይህ ቡድን እዚህ ላይ ሊዋቀር አይችልም"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ማያ ገፅ ቁልፍ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ማስታወሻ ይውሰዱ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ብዙ ተግባራትን በተመሳሳይ ጊዜ ማከናወን"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"መተግበሪያ በስተቀኝ ላይ ሆኖ የተከፈለ ማያ ገፅን ይጠቀሙ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"መተግበሪያ በስተግራ ላይ ሆኖ የተከፈለ ማያ ገፅን ይጠቀሙ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ወደ ሙሉ ገፅ ዕይታ ይቀይሩ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከታች ወዳለ መተግበሪያ ይቀይሩ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"የተከፈለ ማያ ገጽን ሲጠቀሙ በቀኝ ወይም ከላይ ወዳለ መተግበሪያ ይቀይሩ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"በተከፈለ ማያ ገጽ ወቅት፡- መተግበሪያን ከአንዱ ወደ ሌላው ተካ"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"የኃይል ምናሌ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ገፅ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ማያ ገፅ ቁልፍ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ይህ መሣሪያ ኃይል ጠፍቶ ቢሆንም እንኳን በየእኔን መሣሪያ አግኝ ማግኘት ይችላሉ"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"በመዝጋት ላይ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ወደ መነሻ ሂድ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"የቅርብ ጊዜ መተግበሪያዎችን አሳይ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ተከናውኗል"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ወደኋላ ተመለስ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"የመዳሰሻ ሰሌዳዎ ላይ ሦስት ጣቶችን በመጠቀም ወደ ግራ ወይም ወደ ቀኝ ያንሸራትቱ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"አሪፍ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ወደኋላ የመመለስ ምልክትን አጠናቅቀዋል።"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ወደ መነሻ ሂድ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"በመዳሰሻ ሰሌዳዎ ላይ በሦስት ጣቶች ወደ ላይ ያንሸራትቱ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ጥሩ ሥራ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ወደ መነሻ ሂድ ምልክትን አጠናቅቀዋል"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"የቅርብ ጊዜ መተግበሪያዎችን አሳይ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"የመዳሰሻ ሰሌዳዎ ላይ ሦስት ጣቶችን በመጠቀም ወደላይ ያንሸራትቱ እና ይያዙ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ጥሩ ሠርተዋል!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"የቅርብ ጊዜ መተግበሪያዎች አሳይ ምልክትን አጠናቅቀዋል።"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ሁሉንም መተግበሪያዎች ይመልከቱ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"በቁልፍ ሰሌዳዎ ላይ ያለውን የተግባር ቁልፍ ይጫኑ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ጥሩ ሠርተዋል!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"የሁሉንም መተግበሪያዎች አሳይ ምልክትን አጠናቅቀዋል"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"የአጋዥ ሥልጠና እነማ፣ ማጫወትን ባለበት ለማቆም እና ከቆመበት ለመቀጠል ጠቅ ያድርጉ።"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"የቁልፍ ሰሌዳ የጀርባ ብርሃን"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"ደረጃ %1$d ከ %2$d"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 0fc6598..92d0cbb 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -592,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"الإشعارات"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"المحادثات"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"محو جميع الإشعارات الصامتة"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"يؤدي النقر على هذا الزر إلى فتح إعدادات الإشعارات"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"تم إيقاف الإشعارات مؤقتًا وفقًا لإعداد \"عدم الإزعاج\""</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{ما مِن إشعارات}=1{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\"}=2{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" ووضع واحد آخر}few{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# أوضاع أخرى}many{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# وضعًا آخر}other{تم إيقاف الإشعارات مؤقتًا بواسطة \"{mode}\" و# وضع آخر}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"البدء الآن"</string>
@@ -754,6 +753,20 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"اتصالات الطوارئ بالقمر الصناعي"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"مكالمات الطوارئ أو ميزة \"اتصالات طوارئ بالقمر الصناعي\""</string>
+    <!-- no translation found for accessibility_phone_string_format (7798841417881811812) -->
+    <skip />
+    <!-- no translation found for accessibility_no_signal (7052827511409250167) -->
+    <skip />
+    <!-- no translation found for accessibility_one_bar (5342012847647834506) -->
+    <skip />
+    <!-- no translation found for accessibility_two_bars (122628483354508429) -->
+    <skip />
+    <!-- no translation found for accessibility_three_bars (5143286602926069024) -->
+    <skip />
+    <!-- no translation found for accessibility_four_bars (8838495563822541844) -->
+    <skip />
+    <!-- no translation found for accessibility_signal_full (1519655809806462972) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
@@ -787,7 +800,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"تظهر في أعلى إشعارات المحادثات وكصورة ملف شخصي على شاشة القفل وتظهر على شكل فقاعة لمقاطعة ميزة \"عدم الإزعاج\"."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"الأولوية"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"لا يدعم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> ميزات المحادثات."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"تقديم ملاحظات مُجمّعة"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"يتعذّر تعديل هذه الإشعارات."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"لا يمكن تعديل إشعارات المكالمات."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"يتعذّر ضبط مجموعة الإشعارات هذه هنا."</string>
@@ -873,12 +885,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"شاشة القفل"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"تدوين ملاحظة"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"تعدُّد المهام"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق على اليمين"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"استخدام \"وضع تقسيم الشاشة\" مع تثبيت التطبيق على اليسار"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"التبديل إلى وضع ملء الشاشة"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"التبديل إلى التطبيق على اليسار أو الأسفل أثناء استخدام \"تقسيم الشاشة\""</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"التبديل إلى التطبيق على اليمين أو الأعلى أثناء استخدام \"تقسيم الشاشة\""</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"استبدال تطبيق بآخر في وضع \"تقسيم الشاشة\""</string>
@@ -980,7 +989,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"قائمة زر التشغيل"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"شاشة القفل"</string>
-    <string name="finder_active" msgid="7907846989716941952">"يمكنك تحديد مكان هذا الهاتف باستخدام تطبيق \"العثور على جهازي\" حتى عندما يكون مُطفئًا."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"جارٍ إيقاف التشغيل…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"الاطّلاع على خطوات العناية"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"الاطّلاع على خطوات العناية"</string>
@@ -1467,22 +1475,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"الانتقال إلى الصفحة الرئيسية"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"عرض التطبيقات المستخدَمة مؤخرًا"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تم"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"رجوع"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"مرِّر سريعًا لليمين أو لليسار باستخدام 3 أصابع على لوحة اللمس"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"أحسنت."</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"لقد أكملت التدريب على إيماءة الرجوع."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"الانتقال إلى الشاشة الرئيسية"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"مرّر سريعًا للأعلى باستخدام 3 أصابع على لوحة اللمس"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"أحسنت صنعًا."</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"لقد أكملت الدليل التوجيهي عن إيماءة \"الانتقال إلى الشاشة الرئيسية\""</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"عرض التطبيقات المستخدَمة مؤخرًا"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"مرِّر سريعًا للأعلى مع الاستمرار باستخدام 3 أصابع على لوحة اللمس"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"أحسنت."</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"لقد أكملْت التدريب على إيماءة عرض التطبيقات المستخدَمة مؤخرًا."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"عرض جميع التطبيقات"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"اضغط على مفتاح الإجراء في لوحة المفاتيح"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"أحسنت!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"لقد أكملْت التدريب على إيماءة عرض جميع التطبيقات"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"صورة متحركة للدليل التوجيهي: يمكنك النقر عليها لإيقاف تشغيلها مؤقتًا واستئنافه."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"الإضاءة الخلفية للوحة المفاتيح"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏مستوى الإضاءة: %1$d من %2$d"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index b0a9d09..89e5083 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"উপগ্ৰহ SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জৰুৰীকালীন কল বা SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"কোনো ছিগনেল নাই"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"এডাল দণ্ড"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"দুডাল দণ্ড"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"তিনিডাল দণ্ড"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"চাৰিডাল দণ্ড"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"সম্পূৰ্ণ ছিগনেল"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"বাৰ্তালাপৰ জাননীৰ শীৰ্ষত আৰু প্ৰ’ফাইল চিত্ৰ হিচাপে লক স্ক্ৰীনত দেখুৱায়, এটা বাবল হিচাপে দেখা পোৱা যায়, অসুবিধা নিদিব ম’ডত ব্যাঘাত জন্মায়"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"অগ্ৰাধিকাৰ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বাৰ্তালাপৰ সুবিধাসমূহ সমৰ্থন নকৰে"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"বাণ্ডল হিচাপে থকা জাননীত মতামত প্ৰদান কৰক"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"এই জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কলৰ জাননীসমূহ সংশোধন কৰিব নোৱাৰি।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"এই ধৰণৰ জাননীবোৰ ইয়াত কনফিগাৰ কৰিব পৰা নাযায়"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্ৰীন"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"টোকা লিখক"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"সোঁফালে থকা এপ্‌টোৰ সৈতে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"বাওঁফালে থকা এপ্‌টোৰ সৈতে বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰক"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"পূৰ্ণ স্ক্ৰীনলৈ সলনি কৰক"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত সোঁফালে অথবা তলত থকা এপলৈ সলনি কৰক"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"বিভাজিত স্ক্ৰীন ব্যৱহাৰ কৰাৰ সময়ত বাওঁফালে অথবা ওপৰত থকা এপলৈ সলনি কৰক"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"বিভাজিত স্ক্ৰীনৰ ব্যৱহাৰ কৰাৰ সময়ত: কোনো এপ্ এখন স্ক্ৰীনৰ পৰা আনখনলৈ নিয়ক"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাৱাৰ মেনু"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>ৰ পৃষ্ঠা <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীন"</string>
-    <string name="finder_active" msgid="7907846989716941952">"পাৱাৰ অফ কৰা থাকিলেও Find My Deviceৰ জৰিয়তে আপুনি এই ফ’নটোৰ অৱস্থান নিৰ্ধাৰণ কৰিব পাৰে"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"বন্ধ কৰি থকা হৈছে…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"গৃহ পৃষ্ঠালৈ যাওক"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"শেহতীয়া এপ্‌সমূহ চাওক"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হ’ল"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"উভতি যাওক"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"আপোনাৰ টাচ্চপেডত তিনিটা আঙুলি ব্যৱহাৰ কৰি বাওঁফাললৈ বা সোঁফাললৈ ছোৱাইপ কৰক"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"সুন্দৰ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"আপুনি উভতি যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে।"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"গৃহ পৃষ্ঠালৈ যাওক"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"আপোনাৰ টাচ্চপেডত তিনিটা আঙুলিৰে ওপৰলৈ ছোৱাইপ কৰক"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"বঢ়িয়া!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"আপুনি গৃহ স্ক্ৰীনলৈ যোৱাৰ নিৰ্দেশটো সম্পূৰ্ণ কৰিলে"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"শেহতীয়া এপ্‌সমূহ চাওক"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"আপোনাৰ টাচ্চপেডত তিনিটা আঙুলি ব্যৱহাৰ কৰি ওপৰলৈ ছোৱাইপ কৰি ধৰি ৰাখক"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"বঢ়িয়া!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"আপুনি শেহতীয়া এপ্ চোৱাৰ নিৰ্দেশনাটো সম্পূৰ্ণ কৰিছে।"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"আটাইবোৰ এপ্ চাওক"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"আপোনাৰ কীব’ৰ্ডৰ কাৰ্য কীটোত টিপক"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"বঢ়িয়া!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"আপুনি আটাইবোৰ এপ্ চোৱাৰ নিৰ্দেশনাটো সম্পূৰ্ণ কৰিছে"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"টিউট’ৰিয়েল এনিমেশ্বন, পজ কৰিবলৈ আৰু প্লে’ কৰাটো পুনৰ আৰম্ভ কৰিবলৈ ক্লিক কৰক।"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীব’ৰ্ডৰ বেকলাইট"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dৰ %1$d স্তৰ"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 0f59bfb..31238d0 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidcetlər"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Vidcetlər\" qısayolunu əlavə etmək üçün ayarlarda \"Vidcetləri kilidli ekranda göstərin\" seçimi aktiv olmalıdır."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ayarlar"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran qoruyucu düyməsini göstərin"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Təcili peyk bağlantısı"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Təcili zənglər və ya SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"siqnal yoxdur"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"bir zolaq"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"iki zolaq"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"üç zolaq"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"dörd zolaq"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"siqnal tamdır"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Söhbət bildirişlərinin yuxarısında və kilid ekranında profil şəkli kimi göstərilir, baloncuq kimi görünür, Narahat Etməyin rejimini kəsir"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> söhbət funksiyalarını dəstəkləmir"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Paket rəyi təmin edin"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirişlər dəyişdirilə bilməz."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Zəng bildirişləri dəyişdirilə bilməz."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildiriş qrupunu burada konfiqurasiya etmək olmaz"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilid ekranı"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Qeyd götürün"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoxsaylı tapşırıq icrası"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Tətbiq sağda olmaqla bölünmüş ekranı istifadə edin"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Tətbiq solda olmaqla bölünmüş ekranı istifadə edin"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Tam ekran rejiminə keçin"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran istifadə edərkən sağda və ya aşağıda tətbiqə keçin"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran istifadə edərkən solda və ya yuxarıda tətbiqə keçin"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Bölünmüş ekran rejimində: tətbiqi birindən digərinə dəyişin"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Qidalanma düyməsi menyusu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran kilidi"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Bu telefon sönülü olsa belə, Cihazın Tapılması ilə onu tapa bilərsiniz"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Söndürülür…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ehtiyat tədbiri mərhələlərinə baxın"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ehtiyat tədbiri mərhələlərinə baxın"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Əsas səhifəyə keçin"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Son tətbiqlərə baxın"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hazırdır"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri qayıdın"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Taçpeddə üç barmaqla sola və ya sağa sürüşdürün"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Əla!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Geri getmə jestini tamamladınız."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Əsas səhifəyə keçin"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Taçpeddə üç barmaqla yuxarı sürüşdürün"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Əla!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Əsas səhifəyə keçid jestini tamamladınız"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Son tətbiqlərə baxın"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Taçpeddə üç barmaqla yuxarı çəkib saxlayın"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Əla!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son tətbiqlərə baxmaq jestini tamamladınız."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Bütün tətbiqlərə baxın"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klaviaturada fəaliyyət açarına basın"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Əla!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"\"Bütün tətbiqlərə baxın\" jestini tamamladınız"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Öyrədici animasiya, oxudulmanı durdurmaq və davam etdirmək üçün klikləyin."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura işığı"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Səviyyə %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a339b11..6810018 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć preko satelita"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili hitna pomoć"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nema signala"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"jedna crta"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dve crte"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tri crte"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"četiri crte"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal je najjači"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se u vrhu obaveštenja o konverzacijama i kao slika profila na zaključanom ekranu, pojavljuje se kao oblačić, prekida režim Ne uznemiravaj"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije konverzacije"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Pružite povratne informacije o skupu"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ova obaveštenja ne mogu da se menjaju."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obaveštenja o pozivima ne mogu da se menjaju."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ova grupa obaveštenja ne može da se konfiguriše ovde"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Otključavanje ekrana"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Napravi belešku"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka istovremeno"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Koristi podeljeni ekran sa aplikacijom s desne strane"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Koristi podeljeni ekran sa aplikacijom s leve strane"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Pređi na režim preko celog ekrana"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pređi u aplikaciju zdesna ili ispod dok je podeljen ekran"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju sleva ili iznad dok koristite podeljeni ekran"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"U režimu podeljenog ekrana: zamena jedne aplikacije drugom"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni dugmeta za uključivanje"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključan ekran"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Možete da locirate ovaj telefon pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Isključuje se…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pogledajte upozorenja"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte upozorenja"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Idi na početni ekran"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Prikaži nedavno korišćene aplikacije"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Prevucite ulevo ili udesno sa tri prsta na tačpedu"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Super!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Dovršili ste pokret za povratak."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Idi na početni ekran"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Prevucite nagore sa tri prsta na tačpedu"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Odlično!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Dovršili ste pokret za povratak na početnu stranicu."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Prikaži nedavno korišćene aplikacije"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Prevucite nagore i zadržite sa tri prsta na tačpedu"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Odlično!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Dovršili ste pokret za prikazivanje nedavno korišćenih aplikacija."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Prikaži sve aplikacije"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite taster radnji na tastaturi"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Dovršili ste pokret za prikazivanje svih aplikacija."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacija vodiča, kliknite da biste pauzirali i nastavili reprodukciju."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvetljenje tastature"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 9c5a4f2..d95fd67 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Віджэты"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Каб дадаць спалучэнне клавіш \"Віджэты\", у наладах павінна быць уключана функцыя \"Паказваць віджэты на экране блакіроўкі\"."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Налады"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Паказаць застаўку\""</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Экстраннае спадарожнікавае падключэнне"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстранныя выклікі або экстраннае спадарожнікавае падключэнне"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"няма сігналу"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"адзiн слупок"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"два слупкi"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"тры слупкi"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"чатыры слупкі"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"сігнал поўны"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Наладка сістэмнага інтэрфейсу карыстальніка дае вам дадатковыя спосабы наладжвання і дапасоўвання карыстальніцкага інтэрфейсу Android. Гэтыя эксперыментальныя функцыі могуць змяніцца, перастаць працаваць або знікнуць у будучых версіях. Карыстайцеся з асцярожнасцю."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З’яўляецца ўверсе раздзела размоў як усплывальнае апавяшчэнне, якое перарывае рэжым \"Не турбаваць\" і паказвае на экране блакіроўкі відарыс профілю"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не падтрымлівае функцыі размовы"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Пакінуць групавы водгук"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Гэтыя апавяшчэнні нельга змяніць."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Апавяшчэнні пра выклікі нельга змяніць."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Тут канфігурыраваць гэту групу апавяшчэнняў забаронена"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экран блакіроўкі"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Стварыць нататку"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Шматзадачнасць"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Падзяліць экран і памясціць праграму справа"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Падзяліць экран і памясціць праграму злева"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Уключыць поўнаэкранны рэжым"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пераключыцца на праграму справа або ўнізе на падзеленым экране"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пераключыцца на праграму злева або ўверсе на падзеленым экране"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"У рэжыме падзеленага экрана замяніць адну праграму на іншую"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопкі сілкавання"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Экран блакіроўкі"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Вы можаце знайсці свой тэлефон з дапамогай праграмы \"Знайсці прыладу\", нават калі ён выключаны"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Ідзе завяршэнне працы…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Глядзець паэтапную дапамогу"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Глядзець паэтапную дапамогу"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"На галоўную старонку"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прагляд нядаўніх праграм"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Гатова"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Правядзіце па сэнсарнай панэлі трыма пальцамі ўлева ці ўправа"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Выдатна!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Вы навучыліся рабіць жэст вяртання."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На галоўны экран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Правядзіце па сэнсарнай панэлі трыма пальцамі ўверх"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Выдатная праца!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Вы навучыліся рабіць жэст для пераходу на галоўны экран"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прагляд нядаўніх праграм"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Правядзіце па сэнсарнай панэлі трыма пальцамі ўверх і затрымайце пальцы"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Выдатная праца!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы скончылі вывучэнне жэсту для прагляду нядаўніх праграм."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Глядзець усе праграмы"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Націсніце клавішу дзеяння на клавіятуры"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Выдатна!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Вы навучыліся рабіць жэст для прагляду ўсіх праграм"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Анімацыя ў дапаможніку: націсніце, каб прыпыніць ці ўзнавіць прайграванне."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Падсветка клавіятуры"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Узровень %1$d з %2$d"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index ac2edfe..344c011 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS чрез сателит"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Спешни обаждания или SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"няма сигнал"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"една чертичка"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"две чертички"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"три чертички"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"четири чертички"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"сигналът е пълен"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Показва се в горната част на известията за разговори и като снимка на потребителския профил на заключения екран, изглежда като балонче, прекъсва режима „Не безпокойте“"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддържа функциите за разговор"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Предоставяне на отзиви за пакета"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Тези известия не могат да бъдат променяни."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известията за обаждания не могат да бъдат променяни."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Тази група от известия не може да бъде конфигурирана тук"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заключване на екрана"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Създаване на бележка"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Няколко задачи едновременно"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Използване на разделен екран с приложението вдясно"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Използване на разделен екран с приложението вляво"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Превключване на цял екран"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Превключване към приложението вдясно/отдолу в режима на разделен екран"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Превключване към приложението вляво/отгоре в режима на разделен екран"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"При разделен екран: замяна на дадено приложение с друго"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню за включване/изключване"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Заключен екран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Можете да откриете този телефон посредством „Намиране на устройството ми“ дори когато е изключен"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Изключва се…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Вижте стъпките, които да предприемете"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Вижте стъпките, които да предприемете"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Към началния екран"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Преглед на скорошните приложения"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Плъзнете три пръста наляво или надясно по сензорния панел"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Чудесно!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Изпълнихте жеста за връщане назад."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Към началния екран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Плъзнете три пръста нагоре по сензорния панел"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Отлично!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Изпълнихте жеста за преминаване към началния екран"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Преглед на скорошните приложения"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Плъзнете три пръста нагоре по сензорния панел и задръжте"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Отлично!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Изпълнихте жеста за преглед на скорошните приложения."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Преглед на всички приложения"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Натиснете клавиша за действия на клавиатурата си"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Браво!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Изпълнихте жеста за преглед на всички приложения"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Анимация за урока. Кликнете, за да поставите на пауза и да възобновите възпроизвеждането."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка на клавиатурата"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d от %2$d"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c35c62a..d7b24c8 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"উইজেট"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"উইজেট\" শর্টকার্ট যোগ করতে, সেটিংস থেকে \"লক স্ক্রিনে উইজেট দেখুন\" বিকল্প চালু আছে কিনা তা নিশ্চিত করুন।"</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"সেটিংস"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"স্ক্রিন সেভার বোতাম দেখুন"</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>
@@ -701,7 +700,7 @@
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s। মিউট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে মিউট করা হতে পারে।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s। ভাইব্রেট করতে ট্যাপ করুন।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="5743548478357238156">"%1$s। মিউট করতে ট্যাপ করুন।"</string>
-    <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"আশপাশের আওয়াজ কন্ট্রোল করা"</string>
+    <string name="volume_panel_noise_control_title" msgid="7413949943872304474">"নয়েজ কন্ট্রোল"</string>
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"স্পেশিয়ল অডিও"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"বন্ধ আছে"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"চালু আছে"</string>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"স্যাটেলাইট SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জরুরি কল বা SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>।"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"কোনও সিগন্যাল নেই"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"একটি বার"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"দুটি বার"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"তিনটি বার"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"চারটি বার"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"সম্পূর্ণ সিগন্যাল"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"কথোপকথনের বিজ্ঞপ্তির উপরের দিকে এবং প্রোফাইল ছবি হিসেবে লক স্ক্রিনে দেখানো হয়, বাবল হিসেবেও এটি দেখা যায় এবং এর ফলে \'বিরক্ত করবে না\' মোডে কাজ করতে অসুবিধা হয়"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"অগ্রাধিকার"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এ কথোপকথন ফিচার কাজ করে না"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"বান্ডেল সম্পর্কে মতামত দিন"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"এই বিজ্ঞপ্তিগুলি পরিবর্তন করা যাবে না।"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"কল বিজ্ঞপ্তি পরিবর্তন করা যাবে না।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"এই সমস্ত বিজ্ঞপ্তিকে এখানে কনফিগার করা যাবে না"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"লক স্ক্রিন"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"একটি নোট লিখুন"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"মাল্টিটাস্কিং"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ডানদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"বাঁদিকে বর্তমান অ্যাপে স্প্লিট স্ক্রিন ব্যবহার করুন"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ফুল-স্ক্রিন মোডে সুইচ করুন"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"স্প্লিট স্ক্রিন ব্যবহার করার সময় ডানদিকের বা নিচের অ্যাপে পাল্টে নিন"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"স্প্লিট স্ক্রিন ব্যবহার করার সময় বাঁদিকের বা উপরের অ্যাপে পাল্টে নিন"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"\'স্প্লিট স্ক্রিন\' থাকাকালীন: একটি অ্যাপ থেকে অন্যটিতে পাল্টান"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাওয়ার মেনু"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্রিন"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Find My Device-এর মাধ্যমে, ফোনটি বন্ধ করা থাকলেও এটির লোকেশন শনাক্ত করতে পারবেন"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"বন্ধ হচ্ছে…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ডিভাইস রক্ষণাবেক্ষণের ধাপগুলি দেখুন"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ডিভাইস রক্ষণাবেক্ষণের ধাপগুলি দেখুন"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"হোমে যান"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপ দেখুন"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"হয়ে গেছে"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ফিরে যান"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"আপনার টাচপ্যাডে তিনটি আঙুল ব্যবহার করে বাঁদিকে বা ডানদিকে সোয়াইপ করুন"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"সাবাস!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"জেসচার ব্যবহার করে কীভাবে ফিরে যাওয়া যায় সেই সম্পর্কে আপনি জেনেছেন।"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"হোমে যান"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"আপনার টাচপ্যাডে তিনটি আঙুলের সাহায্যে উপরের দিকে সোয়াইপ করুন"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"অসাধারণ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"জেসচার ব্যবহার করে কীভাবে হোমে ফিরে যাওয়া যায় সেই সম্পর্কে আপনি জেনেছেন"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপ দেখুন"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"আপনার টাচপ্যাডে তিনটি আঙুল ব্যবহার করে উপরের দিকে সোয়াইপ করে ধরে রাখুন"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"অসাধারণ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"সম্প্রতি ব্যবহার করা হয়েছে এমন অ্যাপের জেসচার দেখা সম্পূর্ণ করেছেন।"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"সব অ্যাপ দেখুন"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"আপনার কীবোর্ডে অ্যাকশন কী প্রেস করুন"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"দারুণ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"আপনি \'সব অ্যাপের জেসচার দেখুন\' টিউটোরিয়াল সম্পূর্ণ করেছেন"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"টিউটোরিয়াল অ্যানিমেশন পজ করুন এবং আবার চালু করতে ক্লিক করুন।"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"কীবোর্ড ব্যাকলাইট"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-এর মধ্যে %1$d লেভেল"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index f842aab..b858459 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -531,7 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidžeti"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Da dodate prečicu \"Vidžeti\", provjerite je li u postavkama omogućeno \"Prikazuj vidžete na zaključanom ekranu\"."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Postavke"</string>
-    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Prikaži gumb čuvara zaslona"</string>
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Dugme za prikaz čuvara ekrana"</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>
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć putem satelita"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili pomoć"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nema signala"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"jedna crtica"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dvije crtice"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tri crtice"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"četiri crtice"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"pun signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se na vrhu obavještenja u razgovorima i kao slika profila na zaključanom ekranu, izgleda kao oblačić, prekida funkciju Ne ometaj"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava funkcije razgovora"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Pošaljite povratne informacije o paketu"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ta obavještenja se ne mogu izmijeniti."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Nije moguće izmijeniti obavještenja o pozivima."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ovu grupu obavještenja nije moguće konfigurirati ovdje"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Korištenje podijeljenog ekrana s aplikacijom na desnoj strani"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Korištenje podijeljenog ekrana s aplikacijom na lijevoj strani"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Prelazak na prikaz preko cijelog ekrana"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prelazak u aplikaciju desno ili ispod uz podijeljeni ekran"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pređite u aplikaciju lijevo ili iznad dok koristite podijeljeni ekran"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Za vrijeme podijeljenog ekrana: zamjena jedne aplikacije drugom"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni napajanja"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani ekran"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Možete pronaći telefon putem usluge Pronađi moj uređaj čak i kada je isključen"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Isključivanje…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pogledajte korake za zaštitu"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte korake za zaštitu"</string>
@@ -1434,7 +1436,7 @@
     <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Pritisnite tipku da dodijelite prečicu"</string>
     <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Ovo će trajno izbrisati prilagođenu prečicu."</string>
     <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Ovo će trajno izbrisati sve vaše prilagođene prečice."</string>
-    <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Prečica pretraživanja"</string>
+    <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Pretražite prečice"</string>
     <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nema rezultata pretraživanja"</string>
     <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sužavanja"</string>
     <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Ikona tipke radnji ili meta tipka"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Odlazak na početni ekran"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Prikaži nedavne aplikacije"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazad"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Prevucite ulijevo ili udesno s tri prsta na dodirnoj podlozi"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Lijepo!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Savladali ste pokret za vraćanje."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Odlazak na početni ekran"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Prevucite nagore s tri prsta na dodirnoj podlozi"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Sjajno!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Savladali ste pokret za odlazak na početni ekran"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Prikaz nedavnih aplikacija"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Prevucite nagore i zadržite s tri prsta na dodirnoj podlozi"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Sjajno!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvršili ste pokret za prikaz nedavnih aplikacija."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Pogledajte sve aplikacije"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipku radnji na tastaturi"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Izvršili ste pokret za prikaz svih aplikacija"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacija vodiča; pauziranje i nastavak reprodukcije klikom."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tastature"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. nivo od %2$d"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 3386dc0..c8f371c 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS per satèl·lit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Trucades d\'emergència o SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"no hi ha senyal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"una barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dues barres"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tres barres"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"quatre barres"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"senyal complet"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Es mostra a la part superior de les notificacions de les converses i com a foto de perfil a la pantalla de bloqueig, apareix com una bombolla, interromp el mode No molestis"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritat"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admet les funcions de converses"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Proporciona suggeriments sobre el paquet"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Aquestes notificacions no es poden modificar."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notificacions de trucades no es poden modificar."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquest grup de notificacions no es pot configurar aquí"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloqueja la pantalla"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crea una nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasca"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Utilitzar la pantalla dividida amb l\'aplicació a la dreta"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Utilitzar la pantalla dividida amb l\'aplicació a l\'esquerra"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Canviar a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Canvia a l\'aplicació de la dreta o de sota amb la pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Canvia a l\'aplicació de l\'esquerra o de dalt amb la pantalla dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Durant el mode de pantalla dividida: substitueix una app per una altra"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú d\'engegada"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueig"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Pots localitzar aquest telèfon amb Troba el meu dispositiu fins i tot quan estigui apagat"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"S\'està apagant…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Mostra els passos de manteniment"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Mostra els passos de manteniment"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ves a la pantalla d\'inici"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Mostra les aplicacions recents"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fet"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Torna"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Llisca cap a l\'esquerra o cap a la dreta amb tres dits al ratolí tàctil"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Molt bé!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Has completat el gest per tornar enrere."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ves a la pantalla d\'inici"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Llisca cap amunt amb tres dits al ratolí tàctil"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Ben fet!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Has completat el gest per anar a la pantalla d\'inici"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Mostra les aplicacions recents"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Llisca cap amunt amb tres dits i mantén-los premuts al ratolí tàctil"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Ben fet!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completat el gest per veure les aplicacions recents."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Mostra totes les aplicacions"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Prem la tecla d\'acció al teclat"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Enhorabona!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Has completat el gest per veure totes les aplicacions"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animació del tutorial; fes clic per posar en pausa i reprendre la reproducció."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroil·luminació del teclat"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivell %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index c5aea85..efc699b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS přes satelit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tísňová volání nebo SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"není signál"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"jedna čárka"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dvě čárky"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tři čárky"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"čtyři čárky"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"plný signál"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje se v horní části sekce konverzací a na obrazovce uzamčení se objevuje jako profilová fotka, má podobu bubliny a deaktivuje režim Nerušit"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritní"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Zpětná vazba k balíčku"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tato oznámení nelze upravit."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornění na hovor nelze upravit."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Tuto skupinu oznámení tady nelze nakonfigurovat"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknout obrazovku"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Vytvořit poznámku"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Použít rozdělenou obrazovku s aplikací vpravo"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Použít rozdělenou obrazovku s aplikací vlevo"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Přepnout na celou obrazovku"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Přepnout na aplikaci vpravo nebo dole v režimu rozdělené obrazovky"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Přepnout na aplikaci vlevo nebo nahoře v režimu rozdělené obrazovky"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"V režimu rozdělené obrazovky: nahradit jednu aplikaci druhou"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Nabídka vypínače"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Obrazovka uzamčení"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Tento telefon můžete pomocí funkce Najdi moje zařízení najít, i když je vypnutý"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Vypínání…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobrazit pokyny, co dělat"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobrazit pokyny, co dělat"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Přejít na domovskou stránku"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Zobrazit nedávné aplikace"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zpět"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Přejeďte po touchpadu třemi prsty doleva nebo doprava"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Skvělé!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Provedli jste gesto pro přechod zpět."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Přejít na plochu"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Přejeďte po touchpadu třemi prsty nahoru"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Výborně!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Provedli jste gesto pro přechod na plochu"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Zobrazit nedávné aplikace"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Přejeďte po touchpadu třemi prsty nahoru a podržte je"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Výborně!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Provedli jste gesto pro zobrazení nedávných aplikací."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Zobrazit všechny aplikace"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Stiskněte akční klávesu na klávesnici"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Výborně!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Provedli jste gesto k zobrazení všech aplikací"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Výuková animace, kliknutím pozastavíte nebo obnovíte."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvícení klávesnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Úroveň %1$d z %2$d"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 168afad..4336a85 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Hvis du vil tilføje genvejen \"Widgets\", skal du sørge for, at \"Vis widgets på låseskærmen\" er aktiveret i indstillingerne."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Indstillinger"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Knappen Vis pauseskærm"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-meldinger via satellit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødopkald eller SOS-meldinger via satellit"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"intet signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"én bjælke"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"to bjælker"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tre bjælker"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"fire bjælker"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"fuldt signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Vises øverst i samtalenotifikationer og som et profilbillede på låseskærmen. Vises som en boble, der afbryder Forstyr ikke"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke samtalefunktioner"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Giv feedback om pakker"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse notifikationer kan ikke redigeres."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Opkaldsnotifikationer kan ikke redigeres."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Du kan ikke konfigurere denne gruppe notifikationer her"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skærm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Skriv en note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Brug opdelt skærm med appen til højre"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Brug opdelt skærm med appen til venstre"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Skift til fuld skærm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skift til en app til højre eller nedenfor, når du bruger opdelt skærm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skift til en app til venstre eller ovenfor, når du bruger opdelt skærm"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ved opdelt skærm: Udskift én app med en anden"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu for afbryderknappen"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskærm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Du kan finde denne telefon med Find min enhed, også selvom den er slukket"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Lukker ned…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Se håndteringsvejledning"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se håndteringsvejledning"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Gå til startsiden"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se seneste apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Udfør"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbage"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Stryg til venstre eller højre med tre fingre på touchpladen"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Sådan!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du har udført bevægelsen for Gå tilbage."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startskærmen"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Stryg opad med tre fingre på touchpladen"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Flot!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Du har udført bevægelsen for at gå til startsiden"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se seneste apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Stryg opad, og hold tre fingre på touchpladen"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Godt klaret!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har udført bevægelsen for at se de seneste apps."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Se alle apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tryk på handlingstasten på dit tastatur"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Flot klaret!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Du har udført bevægelsen for at se alle apps"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation med vejledning. Klik for at sætte afspilningen på pause og genoptage den."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturets baggrundslys"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d af %2$d"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index bf323dd..6e8cffe 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Zum Hinzufügen der Verknüpfung „Widgets“ musst du zuerst in den Einstellungen die Option „Widgets auf Sperrbildschirm zeigen“ aktivieren."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Einstellungen"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Schaltfläche „Bildschirmschoner anzeigen“"</string>
     <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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Notruf über Satellit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Notrufe oder SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"kein Empfang"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ein Balken"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"zwei Balken"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"drei Balken"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"vier Balken"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"volle Signalstärke"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wird oben im Bereich „Unterhaltungen“ sowie als Profilbild auf dem Sperrbildschirm angezeigt, erscheint als Bubble, unterbricht „Bitte nicht stören“"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorität"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> unterstützt keine Funktionen für Unterhaltungen"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Feedback zu gebündelten Nachrichten geben"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Diese Benachrichtigungen können nicht geändert werden."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anrufbenachrichtigungen können nicht geändert werden."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Die Benachrichtigungsgruppe kann hier nicht konfiguriert werden"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bildschirm sperren"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Notiz machen"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Splitscreen mit der App auf der rechten Seite nutzen"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Splitscreen mit der App auf der linken Seite nutzen"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"In den Vollbildmodus wechseln"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Im Splitscreen-Modus zu einer App rechts oder unten wechseln"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Im Splitscreen-Modus zu einer App links oder oben wechseln"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Im Splitscreen: eine App durch eine andere ersetzen"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ein-/Aus-Menü"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Sperrbildschirm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Du kannst dieses Smartphone über „Mein Gerät finden“ orten, auch wenn es ausgeschaltet ist"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Wird heruntergefahren…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Schritte zur Abkühlung des Geräts ansehen"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Schritte zur Abkühlung des Geräts ansehen"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Zum Startbildschirm"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Letzte Apps aufrufen"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fertig"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Zurück"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Wische mit drei Fingern auf dem Touchpad nach links oder rechts"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Sehr gut!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du hast das Tutorial für die „Zurück“-Touch-Geste abgeschlossen."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Startbildschirm"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Wische an einer beliebigen Stelle auf dem Touchpad mit drei Fingern nach oben"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Gut gemacht!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Du hast den Schritt für die „Startbildschirm“-Touch-Geste abgeschlossen"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Letzte Apps aufrufen"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Wische mit drei Fingern nach oben und halte das Touchpad gedrückt"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Gut gemacht!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du hast das Tutorial für die Touch-Geste zum Aufrufen der zuletzt verwendeten Apps abgeschlossen."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Alle Apps anzeigen"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Drücke die Aktionstaste auf deiner Tastatur"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Perfekt!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Du hast das Tutorial für die Touch-Geste zum Aufrufen aller Apps abgeschlossen"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation während des Tutorials, zum Pausieren und Fortsetzen der Wiedergabe klicken."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastaturbeleuchtung"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d von %2$d"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a90f701..2182220 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Δορυφορικό SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Κλήσεις έκτακτης ανάγκης ή SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"δεν υπάρχει σήμα"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"μία γραμμή"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"δύο γραμμές"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"τρεις γραμμές"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"τέσσερις γραμμές"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"πλήρες σήμα"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Εμφανίζεται στην κορυφή των ειδοποιήσεων συζήτησης και ως φωτογραφία προφίλ στην οθόνη κλειδώματος, εμφανίζεται ως συννεφάκι, διακόπτει τη λειτουργία Μην ενοχλείτε"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Προτεραιότητα"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν υποστηρίζει τις λειτουργίες συζήτησης"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Παροχή σχολίων για πακέτο"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Δεν είναι δυνατή η τροποποίηση αυτών των ειδοποιήσεων"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Δεν είναι δυνατή η τροποποίηση των ειδοποιήσεων κλήσεων."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Δεν είναι δυνατή η διαμόρφωση αυτής της ομάδας ειδοποιήσεων εδώ"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Κλείδωμα οθόνης"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Δημιουργία σημείωσης"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Πολυδιεργασία"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Χρήση διαχωρισμού οθόνης με την εφαρμογή στα δεξιά"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Χρήση διαχωρισμού οθόνης με την εφαρμογή στα αριστερά"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Εναλλαγή σε πλήρη οθόνη"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Εναλλαγή στην εφαρμογή δεξιά ή κάτω κατά τη χρήση διαχωρισμού οθόνης"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Εναλλαγή σε εφαρμογή αριστερά ή επάνω κατά τη χρήση διαχωρισμού οθόνης"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Κατά τον διαχωρισμό οθόνης: αντικατάσταση μιας εφαρμογής με άλλη"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Μενού λειτουργίας"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Οθόνη κλειδώματος"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Μπορείτε να εντοπίσετε το συγκεκριμένο τηλέφωνο με την Εύρεση συσκευής ακόμα και όταν είναι απενεργοποιημένο"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Τερματισμός λειτουργίας…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Δείτε βήματα αντιμετώπισης."</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Δείτε βήματα αντιμετώπισης."</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Αρχική"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Προβολή πρόσφατων εφαρμογών"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Τέλος"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Επιστροφή"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Σύρετε προς τα αριστερά ή τα δεξιά με τρία δάχτυλα στην επιφάνεια αφής"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Ωραία!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ολοκληρώσατε την κίνηση επιστροφής."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Αρχική"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Σύρετε προς τα επάνω με τρία δάχτυλα στην επιφάνεια αφής"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Μπράβο!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ολοκληρώσατε την κίνηση μετάβασης στην αρχική οθόνη"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Προβολή πρόσφατων εφαρμογών"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Σύρετε προς τα επάνω με τρία δάχτυλα στην επιφάνεια αφής και μην τα σηκώσετε"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Μπράβο!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ολοκληρώσατε την κίνηση για την προβολή πρόσφατων εφαρμογών."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Προβολή όλων των εφαρμογών"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Πατήστε το πλήκτρο ενέργειας στο πληκτρολόγιό σας"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Μπράβο!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Ολοκληρώσατε την κίνηση για την προβολή όλων των εφαρμογών"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Κινούμενη εικόνα οδηγού, κάντε κλικ για παύση και συνέχιση της αναπαραγωγής."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Οπίσθιος φωτισμός πληκτρολογίου"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Επίπεδο %1$d από %2$d"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 679684a..779e3f6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"No signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"one bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"two bars"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"three bars"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"four bars"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal full"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Provide bundle feedback"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Use split screen with app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Use split screen with app on the left"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Switch to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"During split screen: Replace an app from one to another"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
-    <string name="finder_active" msgid="7907846989716941952">"You can locate this phone with Find My Device even when powered off"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Shutting down…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"See care steps"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Well done!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial animation, click to pause and resume play."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index f54745d..22916c3 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"no signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"one bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"two bars"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"three bars"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"four bars"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal full"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Provide Bundle Feedback"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -976,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
-    <string name="finder_active" msgid="7907846989716941952">"You can locate this phone with Find My Device even when powered off"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Shutting down…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"See care steps"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string>
@@ -1463,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"Try again!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"To go back using your touchpad, swipe left or right using three fingers"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Great job!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"Swipe up with three fingers on your touchpad to go to your home screen"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Great job!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"To view recent apps, swipe up and hold using three fingers on your touchpad"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"Press the action key on your keyboard to view all of your apps"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial animation, click to pause and resume play."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 679684a..779e3f6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"No signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"one bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"two bars"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"three bars"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"four bars"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal full"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Provide bundle feedback"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Use split screen with app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Use split screen with app on the left"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Switch to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"During split screen: Replace an app from one to another"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
-    <string name="finder_active" msgid="7907846989716941952">"You can locate this phone with Find My Device even when powered off"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Shutting down…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"See care steps"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Well done!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial animation, click to pause and resume play."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 679684a..779e3f6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"To add the \'Widgets\' shortcut, make sure that \'Show widgets on lock screen\' is enabled in settings."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Settings"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Show screensaver button"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"No signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"one bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"two bars"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"three bars"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"four bars"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal full"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shows at the top of conversation notifications and as a profile picture on lock screen, appears as a bubble, interrupts Do Not Disturb"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> doesn’t support conversation features"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Provide bundle feedback"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"These notifications can\'t be modified."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Call notifications can\'t be modified."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"This group of notifications cannot be configured here"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lock screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Take a note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-tasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Use split screen with app on the right"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Use split screen with app on the left"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Switch to full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Switch to the app on the right or below while using split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Switch to the app on the left or above while using split screen"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"During split screen: Replace an app from one to another"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> of <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
-    <string name="finder_active" msgid="7907846989716941952">"You can locate this phone with Find My Device even when powered off"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Shutting down…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"See care steps"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Go home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"View recent apps"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Done"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Go back"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe left or right using three fingers on your touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Nice!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"You completed the go back gesture."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Go home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe up with three fingers on your touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Well done!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"You completed the go home gesture"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"View recent apps"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe up and hold using three fingers on your touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Well done!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"You completed the view recent apps gesture."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"View all apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Press the action key on your keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Well done!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"You completed the view all apps gesture"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial animation, click to pause and resume play."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Keyboard backlight"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d of %2$d"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ca53976..1f3aee8 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"sin señal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"una barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dos barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tres barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"cuatro barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"señal completa"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunas personas"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparece en forma de burbuja y como foto de perfil en la parte superior de las notificaciones de conversación, en la pantalla de bloqueo, y detiene el modo No interrumpir"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaria"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Proporcionar comentarios sobre el conjunto"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"No se pueden modificar estas notificaciones."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"No se pueden modificar las notificaciones de llamada."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"No se puede configurar aquí este grupo de notificaciones"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloquear la pantalla"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear una nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Tareas múltiples"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Usar la pantalla dividida con la app a la derecha"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Usar la pantalla dividida con la app a la izquierda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Cambiar a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ubicar la app a la derecha o abajo cuando usas la pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ubicar la app a la izquierda o arriba cuando usas la pantalla dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante pantalla dividida: Reemplaza una app con otra"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de encendido"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Puedes ubicar este teléfono con Encontrar mi dispositivo, incluso si está apagado"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Apagando…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver pasos de mantenimiento"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantenimiento"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ir a la página principal"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver apps recientes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Listo"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"¡Muy bien!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Completaste el gesto para ir atrás."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a la página principal"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Desliza hacia arriba con tres dedos en el panel táctil"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"¡Bien hecho!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Completaste el gesto para ir a la página principal"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver apps recientes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Desliza hacia arriba con tres dedos en el panel táctil y mantenlos presionados"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"¡Bien hecho!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaste el gesto para ver las apps recientes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas las apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Presiona la tecla de acción en el teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"¡Bien hecho!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Completaste el gesto para ver todas las apps"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animación del instructivo. Haz clic para pausar y reanudar la reproducción."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 28812cc..8ae684a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para añadir el acceso directo Widgets, asegúrate de que la opción Mostrar widgets en la pantalla de bloqueo esté habilitada en los ajustes."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ajustes"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botón para mostrar el salvapantallas"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"no hay señal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"una barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dos barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tres barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"cuatro barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"señal al máximo"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Se muestra encima de las notificaciones de conversaciones y como imagen de perfil en la pantalla de bloqueo, aparece como burbuja e interrumpe el modo No molestar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Enviar comentarios sobre el paquete"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificaciones no se pueden modificar."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Las notificaciones de llamada no se pueden modificar."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Este grupo de notificaciones no se puede configurar aquí"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Escribir una nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarea"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Usar la pantalla dividida con la aplicación a la derecha"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Usar la pantalla dividida con la aplicación a la izquierda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Cambiar a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar a la aplicación de la derecha o de abajo en pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar a la app de la izquierda o de arriba en pantalla dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Con pantalla dividida: reemplazar una aplicación por otra"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de encendido"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Puedes localizar este teléfono con Encontrar mi dispositivo, aunque esté apagado"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Apagando…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver pasos de mantenimiento"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantenimiento"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ir a Inicio"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver aplicaciones recientes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hecho"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atrás"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Desliza hacia la izquierda o la derecha con tres dedos en el panel táctil"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"¡Genial!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Has completado el gesto para volver."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir a Inicio"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Desliza hacia arriba con tres dedos en el panel táctil"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"¡Bien hecho!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Has completado el gesto para ir a la pantalla de inicio"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver aplicaciones recientes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Desliza hacia arriba con tres dedos y mantén pulsado en el panel táctil"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"¡Bien hecho!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Has completado el gesto para ver las aplicaciones recientes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas las aplicaciones"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pulsa la tecla de acción de tu teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"¡Muy bien!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Has completado el gesto para ver todas las aplicaciones"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animación del tutorial, haz clic para pausar y reanudar la reproducción."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación del teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 2c0c378..e3e7263 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidinad"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Otsetee „Vidinad“ lisamiseks veenduge, et seadetes oleks valik „Kuva lukustuskuval vidinad“ lubatud."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Seaded"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Nupp Kuva ekraanisäästja"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliit-SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hädaabikõned või SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"signaal puudub"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"üks pulk"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"kaks pulka"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"kolm pulka"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"neli pulka"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"tugev signaal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Kuvatakse mullina vestluste märguannete ülaosas ja profiilipildina lukustuskuval ning katkestab režiimi Mitte segada"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteetne"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei toeta vestlusfunktsioone"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Kogumi kohta tagasiside andmine"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Neid märguandeid ei saa muuta."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Kõnemärguandeid ei saa muuta."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Seda märguannete rühma ei saa siin seadistada"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukustuskuva"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Märkme tegemine"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitegumtöö"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Jagatud ekraanikuva kasutamine, rakendus kuvatakse paremal"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Jagatud ekraanikuva kasutamine, rakendus kuvatakse vasakul"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Täisekraanile lülitamine"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Paremale või alumisele rakendusele lülitamine jagatud ekraani ajal"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vasakule või ülemisele rakendusele lülitamine jagatud ekraani ajal"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ekraanikuva jagamise ajal: ühe rakenduse asendamine teisega"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Toitemenüü"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lukustuskuva"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Saate selle telefoni funktsiooniga Leia mu seade leida ka siis, kui see on välja lülitatud"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Väljalülitamine …"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Vaadake hooldusjuhiseid"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vaadake hooldusjuhiseid"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Avakuvale"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Hiljutiste rakenduste vaatamine"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tagasi"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Pühkige puuteplaadil kolme sõrmega vasakule või paremale"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Tubli töö!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Tegite tagasiliikumise liigutuse."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Avakuvale"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Pühkige puuteplaadil kolme sõrmega üles"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Väga hea!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Tegite avakuvale minemise liigutuse"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Hiljutiste rakenduste vaatamine"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Pühkige üles ja hoidke kolme sõrme puuteplaadil"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Väga hea!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Tegite hiljutiste rakenduste vaatamise liigutuse."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Kõigi rakenduste kuvamine"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Vajutage klaviatuuril toiminguklahvi"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Hästi tehtud!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Tegite kõigi rakenduste vaatamise liigutuse"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Õpetlik animatsioon, klõpsake esitamise peatamiseks ja jätkamiseks."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatuuri taustavalgustus"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tase %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index cfd6c6a..e284597 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetak"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Widgetak\" lasterbidea gehitzeko, ziurtatu \"Erakutsi widgetak pantaila blokeatuan\" gaituta dagoela ezarpenetan."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ezarpenak"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Erakutsi pantaila-babeslearen 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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelite bidezko SOS komunikazioa"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Larrialdi-deiak edo SOS komunikazioa"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ez dago seinalerik"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"barra bat"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"bi barra"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"hiru barra"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"lau barra"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"seinale osoa"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Elkarrizketen jakinarazpenen goialdean eta profileko argazki gisa agertzen da pantaila blokeatuan, burbuila batean, eta ez molestatzeko modua eteten du"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Lehentasuna"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez ditu onartzen elkarrizketetarako eginbideak"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Bidali sortari buruzko oharrak"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Jakinarazpen horiek ezin dira aldatu."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Deien jakinarazpenak ezin dira aldatu."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Jakinarazpen talde hau ezin da konfiguratu hemen"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Egin ohar bat"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Zeregin bat baino gehiago aldi berean exekutatzea"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Erabili pantaila zatitua eta ezarri aplikazio hau eskuinean"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Erabili pantaila zatitua eta ezarri aplikazio hau ezkerrean"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Aldatu pantaila osora"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Aldatu eskuineko edo beheko aplikaziora pantaila zatitua erabiltzean"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Aldatu ezkerreko edo goiko aplikaziora pantaila zatitua erabiltzean"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Pantaila zatituan zaudela, ordeztu aplikazio bat beste batekin"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Itzaltzeko menua"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantaila blokeatua"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Itzalita badago ere aurki dezakezu telefonoa Bilatu nire gailua erabilita"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Itzaltzen…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ikusi zaintzeko urratsak"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ikusi zaintzeko urratsak"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Joan orri nagusira"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ikusi azkenaldiko aplikazioak"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Eginda"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Egin atzera"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Pasatu 3 hatz ezkerrera edo eskuinera ukipen-panelean"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Ederki!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ikasi duzu atzera egiteko keinua."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Joan orri nagusira"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Pasatu 3 hatz gora ukipen-panelean"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bikain!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ikasi duzu orri nagusira joateko keinua"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ikusi azkenaldiko aplikazioak"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Pasatu 3 hatz gora eta eduki sakatuta ukipen-panelean"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bikain!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Osatu duzu azkenaldiko aplikazioak ikusteko keinua."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ikusi aplikazio guztiak"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Sakatu teklatuko ekintza-tekla"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bikain!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Osatu duzu aplikazio guztiak ikusteko keinua"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorialeko animazioa. Sakatu pausatzeko eta erreproduzitzeari berrekiteko."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Teklatuaren hondoko argia"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d/%2$d maila"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 163d84b..0abbd26 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ابزاره‌ها"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"برای افزودن میان‌بر «ابزاره‌ها»، مطمئن شوید «نمایش ابزاره‌ها در صفحه قفل» در تنظیمات فعال باشد."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"تنظیمات"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"دکمه نمایش دادن محافظ صفحه‌نمایش"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"درخواست کمک ماهواره‌ای"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"تماس اضطراری یا درخواست کمک اضطراری"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"‫<xliff:g id="CARRIER_NAME">%1$s</xliff:g>، <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"سیگنال وجود ندارد"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"یک خط"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"دو خط"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"سه خط"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"چهار خط"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"سیگنال کامل"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرم‌کننده است اما نه برای همه"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏«تنظیم‌کننده واسط کاربری سیستم» روش‌های بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار می‌دهد. ممکن است این ویژگی‌های آزمایشی تغییر کنند، خراب شوند یا در نسخه‌های آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"در بالای اعلان‌های مکالمه و به‌صورت عکس نمایه در صفحه قفل نشان داده می‌شود، به‌صورت حبابک ظاهر می‌شود، در حالت «مزاحم نشوید» وقفه ایجاد می‌کند"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> از ویژگی‌های مکالمه پشتیبانی نمی‌کند"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ارائه بازخورد دسته‌ای"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"این اعلان‌ها قابل اصلاح نیستند."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"این اعلان‌ها قابل‌اصلاح نیستند."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"نمی‌توانید این گروه اعلان‌ها را در اینجا پیکربندی کنید"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"قفل صفحه"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"یادداشت‌برداری"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"چندوظیفگی"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"استفاده از صفحهٔ دونیمه با قرار گرفتن برنامه در سمت راست"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"استفاده از صفحهٔ دونیمه با قرار گرفتن برنامه در سمت چپ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"رفتن به حالت تمام‌صفحه"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"رفتن به برنامه سمت راست یا پایین درحین استفاده از صفحهٔ دونیمه"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"رفتن به برنامه سمت چپ یا بالا درحین استفاده از صفحهٔ دونیمه"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"درحین صفحهٔ دونیمه: برنامه‌ای را با دیگری جابه‌جا می‌کند"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"منوی روشن/خاموش"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"صفحه قفل"</string>
-    <string name="finder_active" msgid="7907846989716941952">"حتی وقتی این تلفن خاموش است، می‌توانید با «پیدا کردن دستگاهم» آن را مکان‌یابی کنید"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"درحال خاموش شدن…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"دیدن اقدامات محافظتی"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"دیدن اقدامات محافظتی"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"رفتن به صفحه اصلی"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"مشاهده برنامه‌های اخیر"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"تمام"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"برگشتن"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"با سه انگشت روی صفحه لمسی تند به چپ یا راست بکشید."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"چه خوب!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"اشاره برگشت را تکمیل کردید."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"رفتن به صفحه اصلی"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"با سه انگشت روی صفحه لمسی تند به بالا بکشید"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"عالی است!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"اشاره رفتن به صفحه اصلی را تکمیل کردید"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"مشاهده برنامه‌های اخیر"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"با سه انگشت روی صفحه لمسی تند به بالا بکشید و نگه دارید"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"عالی است!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"اشاره «مشاهده برنامه‌های اخیر» را تمام کردید"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"مشاهده همه برنامه‌ها"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"دکمه کنش را روی صفحه لمسی فشار دهید"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"عالی بود!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"اشاره «مشاهده همه برنامه‌ها» را تمام کردید"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"پویانمایی آموزش گام‌به‌گام، برای توقف موقت و ازسرگیری پخش کلیک کنید."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"نور پس‌زمینه صفحه‌کلید"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏سطح %1$d از %2$d"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 1caac76..03d1441 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetit"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Jos haluat lisätä Widgetit-pikakuvakkeen, varmista, että \"Näytä widgetit lukitusnäytöllä\" on käytössä asetuksissa."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Asetukset"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Näytä näytönsäästäjän painike"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hätäpuhelut tai Satellite SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ei signaalia"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"yksi palkki"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"kaksi palkkia"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"kolme palkkia"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"neljä palkkia"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"vahva signaali"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Näkyy keskusteluilmoitusten yläosassa ja profiilikuvana lukitusnäytöllä, näkyy kuplana, keskeyttää Älä häiritse ‑tilan"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Tärkeä"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei tue keskusteluominaisuuksia"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Anna palautetta paketista"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Näitä ilmoituksia ei voi muokata"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Puheluilmoituksia ei voi muokata."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Tätä ilmoitusryhmää ei voi määrittää tässä"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lukitse näyttö"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Tee muistiinpano"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitaskaus"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Käytä jaettua näyttöä niin, että sovellus on oikealla"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Käytä jaettua näyttöä niin, että sovellus on vasemmalla"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Koko näytölle siirtyminen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Vaihda sovellukseen oikealla tai alapuolella jaetussa näytössä"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Vaihda sovellukseen vasemmalla tai yläpuolella jaetussa näytössä"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Jaetun näytön aikana: korvaa sovellus toisella"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Virtavalikko"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lukitusnäyttö"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Voit löytää tämän puhelimen Paikanna laite ‑sovelluksella, vaikka se olisi sammutettuna"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Sammutetaan…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Katso huoltovaiheet"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Katso huoltovaiheet"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Siirry etusivulle"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Katso viimeisimmät sovellukset"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Valmis"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Takaisin"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Pyyhkäise kosketuslevyllä vasemmalle tai oikealle kolmella sormella"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Hienoa!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Olet oppinut Takaisin-eleen."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Siirry etusivulle"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Pyyhkäise ylös kolmella sormella kosketuslevyllä"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Hienoa!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Olet oppinut eleen, jolla pääset takaisin aloitusnäytölle"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Katso viimeisimmät sovellukset"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Pyyhkäise ylös ja pidä kosketuslevyä painettuna kolmella sormella"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Hienoa!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Olet oppinut Katso viimeisimmät sovellukset ‑eleen."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Näytä kaikki sovellukset"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Paina näppäimistön toimintonäppäintä"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Hienoa!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Olet oppinut Näytä kaikki sovellukset ‑eleen."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Ohjeanimaatio, klikkaa keskeyttääksesi ja jatkaaksesi."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Näppämistön taustavalo"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Taso %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6d56ac1..f55fb00 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pour ajouter le raccourci « Widgets », assurez-vous que « Afficher les widgets sur l\'écran de verrouillage » est activé dans les paramètres."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Paramètres"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Afficher le bouton de l\'écran de veille"</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 applis et les données de cette session seront supprimées."</string>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"aucun signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"une barre"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"deux barres"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"trois barres"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"quatre barres"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal excellent"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"S\'affiche dans le haut des notifications de conversation et comme photo de profil à l\'écran de verrouillage, s\'affiche comme bulle, interrompt le mode Ne pas déranger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne prend pas en charge les fonctionnalités de conversation"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Fournir des commentaires groupés"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ces notifications ne peuvent pas être modifiées"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Les notifications d\'appel ne peuvent pas être modifiées."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ce groupe de notifications ne peut pas être configuré ici"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Verrouiller l\'écran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Prendre une note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Utiliser l\'Écran divisé avec l\'appli à droite"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Utiliser l\'Écran divisé avec l\'appli à gauche"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Passer au mode plein écran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passer à l\'appli à droite ou en dessous avec l\'Écran divisé"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passer à l\'appli à gauche ou au-dessus avec l\'Écran divisé"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"En mode d\'écran divisé : remplacer une appli par une autre"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu de l\'interrupteur"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Écran de verrouillage"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Vous pouvez localiser ce téléphone à l\'aide de Localiser mon appareil, même lorsqu\'il est éteint"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Arrêt en cours…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Afficher les étapes d\'entretien"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Retour à la page d\'accueil"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Afficher les applis récentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Balayez votre pavé tactile vers la gauche ou vers la droite avec trois doigts"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bien!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Vous avez appris le geste de retour en arrière."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à la page d\'accueil"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Balayez votre pavé tactile vers le haut avec trois doigts"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bon travail!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Vous avez appris le geste pour revenir à l\'écran d\'accueil"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Afficher les applis récentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Balayez votre pavé tactile vers le haut avec trois doigts, puis maintenez-les en place"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bon travail!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez effectué le geste pour afficher les applis récentes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Afficher toutes les applis"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Appuyez sur la touche d\'action de votre clavier"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Félicitations!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Vous avez appris le geste pour afficher toutes les applis"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation du tutoriel; cliquer ici pour mettre en pause et reprendre la lecture."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index fd9854b..138cfc9 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pour ajouter le raccourci \"Widgets\", assurez-vous que l\'option \"Afficher les widgets sur l\'écran de verrouillage\" est activée dans les paramètres."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Paramètres"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Afficher le bouton \"Économiseur d\'écran\""</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>
@@ -643,7 +642,7 @@
     <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"Vos applis personnelles sont connectées à Internet via <xliff:g id="VPN_APP">%1$s</xliff:g>. Votre fournisseur de VPN a accès à votre activité réseau (e-mails, données de navigation, etc.)."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Ouvrir les paramètres VPN"</string>
-    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par tes parents. Ils peuvent voir et gérer certaines informations, telles que les applications que tu utilises, ta position et ton temps d\'utilisation de l\'appareil."</string>
+    <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par tes parents. Ils peuvent voir et gérer certaines informations, telles que les applications que tu utilises, ta position et ton temps devant l\'écran."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"Maintenu déverrouillé par TrustAgent"</string>
     <string name="kg_prompt_after_adaptive_auth_lock" msgid="2587481497846342760">"L\'appareil a été verrouillé, trop de tentatives d\'authentification"</string>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"aucun signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"faible"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"moyen"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"bon"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"très bon"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"excellent signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"S\'affiche en haut des notifications de conversation et en tant que photo de profil sur l\'écran de verrouillage, apparaît sous forme de bulle, interrompt le mode Ne pas déranger"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec les fonctionnalités de conversation"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Envoyer des commentaires groupés"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossible de modifier ces notifications."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossible de modifier les notifications d\'appel."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Vous ne pouvez pas configurer ce groupe de notifications ici"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Verrouiller l\'écran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Créer une note"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitâche"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Utiliser l\'écran partagé avec l\'appli sur la droite"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Utiliser l\'écran partagé avec l\'appli sur la gauche"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Passer en plein écran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Passer à l\'appli à droite ou en dessous avec l\'écran partagé"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Passez à l\'appli à gauche ou au-dessus avec l\'écran partagé"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"En mode écran partagé : Remplacer une appli par une autre"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu Marche/Arrêt"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Écran de verrouillage"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Vous pouvez localiser ce téléphone avec Localiser mon appareil même lorsqu\'il est éteint"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Arrêt…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Afficher les étapes d\'entretien"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string>
@@ -1424,7 +1425,7 @@
     <string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"Applis système"</string>
     <string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitâche"</string>
     <string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Écran partagé"</string>
-    <string name="shortcut_helper_category_input" msgid="8674018654124839566">"Entrée"</string>
+    <string name="shortcut_helper_category_input" msgid="8674018654124839566">"Saisie"</string>
     <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Raccourcis d\'application"</string>
     <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Appli actuelle"</string>
     <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accessibilité"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Retour à l\'accueil"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Afficher les applis récentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"OK"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Retour"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Balayez vers la gauche ou la droite avec trois doigts sur le pavé tactile"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bravo !"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Vous avez appris le geste pour revenir en arrière"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Retour à l\'accueil"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Balayez vers le haut avec trois doigts sur le pavé tactile"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bravo !"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Vous avez appris le geste pour revenir à l\'écran d\'accueil"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Afficher les applis récentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Avec trois doigts, balayez le pavé tactile vers le haut et maintenez la position"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bravo !"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Vous avez appris le geste pour afficher les applis récentes"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Afficher toutes les applications"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Appuyez sur la touche d\'action de votre clavier"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bravo !"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Vous avez appris le geste pour afficher toutes les applis"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation du tutoriel, cliquez pour mettre en pause et reprendre la lecture."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Rétroéclairage du clavier"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d sur %2$d"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 96b858b6..d04d043 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para engadir o atallo Widgets, vai a Configuración e comproba que está activada a opción Mostrar widgets na pantalla de bloqueo."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configuración"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botón para mostrar o protector de pantalla"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emerxencia ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"non hai cobertura"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"unha barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dúas barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tres barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"catro barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinal completo"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Móstrase na parte superior das notificacións das conversas e como imaxe do perfil na pantalla de bloqueo, aparece como unha burbulla e interrompe o modo Non molestar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite funcións de conversa"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Enviar comentarios agrupados"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Estas notificacións non se poden modificar."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"As notificacións de chamadas non se poden modificar."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Aquí non se pode configurar este grupo de notificacións"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Pantalla de bloqueo"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Crear nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefa"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Usar pantalla dividida coa aplicación na dereita"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Usar pantalla dividida coa aplicación na esquerda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Cambiar a pantalla completa"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Cambiar á aplicación da dereita ou de abaixo coa pantalla dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Cambiar á aplicación da esquerda ou de arriba coa pantalla dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"En modo de pantalla dividida: Substituír unha aplicación por outra"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de acendido"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Podes atopar este teléfono (mesmo se está apagado) con Localizar o meu dispositivo"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Apagando…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver pasos de mantemento"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantemento"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ir ao inicio"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Consultar aplicacións recentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Feito"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Volver"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Pasa tres dedos cara á esquerda ou cara á dereita no panel táctil"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Excelente!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Completaches o titorial do xesto de retroceso."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir ao inicio"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Pasa tres dedos cara arriba no panel táctil"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Ben feito!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Completaches o titorial do xesto para ir á pantalla de inicio"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Consultar aplicacións recentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Pasa tres dedos cara arriba e mantenos premidos no panel táctil"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Moi ben!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Completaches o titorial do xesto de consultar aplicacións recentes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas as aplicacións"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Preme a tecla de acción do teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Ben feito!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Completaches o titorial do xesto de ver todas as aplicacións"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animación do titorial, fai clic para poñelo en pausa ou retomar a reprodución."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroiluminación do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivel %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index fb494c1..327753d 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"વિજેટ"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"વિજેટ\"નો શૉર્ટકટ ઉમેરવા માટે, ખાતરી કરો કે સેટિંગમાં \"લૉક સ્ક્રીન પર વિજેટ બતાવો\" સુવિધા ચાલુ કરેલી છે."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"સેટિંગ"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"સ્ક્રીનસેવર બટન બતાવો"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ઇમર્જન્સી સૅટલાઇટ સહાય"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ઇમર્જન્સી કૉલ અથવા SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"કોઈ સિગ્નલ નથી"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"એક બાર"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"બે બાર"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"ત્રણ બાર"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ચાર બાર"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"સિગ્નલ પૂર્ણ છે"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"વાતચીતના નોટિફિકેશન વિભાગની ટોચ પર અને લૉક કરેલી સ્ક્રીન પર પ્રોફાઇલ ફોટો તરીકે બતાવે છે, બબલ તરીકે દેખાય છે, ખલેલ પાડશો નહીં મોડમાં વિક્ષેપ ઊભો કરે છે"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"પ્રાધાન્યતા"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> વાતચીતની સુવિધાઓને સપોર્ટ આપતી નથી"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"બંડલ પ્રતિસાદ પ્રદાન કરો"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"આ નોટિફિકેશનમાં કોઈ ફેરફાર થઈ શકશે નહીં."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"કૉલના નોટિફિકેશનમાં કોઈ ફેરફાર કરી શકાતો નથી."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"નોટિફિકેશનના આ ગ્રૂપની ગોઠવણી અહીં કરી શકાશે નહીં"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"લૉક સ્ક્રીન"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"નોંધ લો"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"એકસાથે એકથી વધુ કાર્યો કરવા"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"હાલની ઍપને જમણી બાજુએ રાખીને વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"હાલની ઍપને ડાબી બાજુએ રાખીને વિભાજિત સ્ક્રીનનો ઉપયોગ કરો"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"પૂર્ણ સ્ક્રીન પર સ્વિચ કરો"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે જમણી બાજુ કે નીચેની ઍપ પર સ્વિચ કરો"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"વિભાજિત સ્ક્રીનનો ઉપયોગ કરતી વખતે ડાબી બાજુની કે ઉપરની ઍપ પર સ્વિચ કરો"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"વિભાજિત સ્ક્રીન દરમિયાન: એક ઍપને બીજી ઍપમાં બદલો"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"પાવર મેનૂ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"લૉક સ્ક્રીન"</string>
-    <string name="finder_active" msgid="7907846989716941952">"આ ફોનનો પાવર બંધ હોય ત્યારે પણ Find My Device વડે તમે તેનું લોકેશન જાણી શકો છો"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"શટ ડાઉન કરી રહ્યાં છીએ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"સારસંભાળના પગલાં જુઓ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"સારસંભાળના પગલાં જુઓ"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"હોમ પર જાઓ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"તાજેતરની ઍપ જુઓ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"થઈ ગયું"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"પાછા જાઓ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"તમારા ટચપૅડ પર ત્રણ આંગળીનો ઉપયોગ કરીને ડાબે કે જમણે સ્વાઇપ કરો"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"સરસ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"તમે પાછા જવાનો સંકેત પૂર્ણ કર્યો છે."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"હોમ પર જાઓ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"તમારા ટચપૅડ પર ત્રણ આંગળી વડે ઉપરની તરફ સ્વાઇપ કરો"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ખૂબ સરસ કામ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"તમે હોમ સ્ક્રીન પર જવાનો સંકેત પૂર્ણ કર્યો"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"તાજેતરની ઍપ જુઓ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"તમારા ટચપૅડ પર ત્રણ આંગળીઓનો ઉપયોગ કરીને ઉપર સ્વાઇપ કરો અને દબાવી રાખો"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ખૂબ સરસ કામ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"તમે \'તાજેતરની ઍપ જુઓ\' સંકેત પૂર્ણ કર્યો."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"બધી ઍપ જુઓ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"તમારા કીબોર્ડ પરની ઍક્શન કી દબાવો"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"વાહ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"તમે \'બધી ઍપ જુઓ\' સંકેત પૂર્ણ કર્યો"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ટ્યૂટૉરિઅલ ઍનિમેશન થોભાવવાનું અને ચલાવવાનું ફરી શરૂ કરવા માટે ક્લિક કરો."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"કીબોર્ડની બૅકલાઇટ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dમાંથી %1$d લેવલ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c84a3eb..1d3280c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -753,6 +753,20 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"सैटलाइट एसओएस"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपातकालीन कॉल या एसओएस"</string>
+    <!-- no translation found for accessibility_phone_string_format (7798841417881811812) -->
+    <skip />
+    <!-- no translation found for accessibility_no_signal (7052827511409250167) -->
+    <skip />
+    <!-- no translation found for accessibility_one_bar (5342012847647834506) -->
+    <skip />
+    <!-- no translation found for accessibility_two_bars (122628483354508429) -->
+    <skip />
+    <!-- no translation found for accessibility_three_bars (5143286602926069024) -->
+    <skip />
+    <!-- no translation found for accessibility_four_bars (8838495563822541844) -->
+    <skip />
+    <!-- no translation found for accessibility_signal_full (1519655809806462972) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
@@ -786,7 +800,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यह कई तरीकों से दिखती है, जैसे कि बातचीत वाली सूचनाओं में सबसे ऊपर, बबल के तौर पर, और लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो के तौर पर. साथ ही, यह \'परेशान न करें\' मोड को बायपास कर सकती है"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"बंडल के बारे में सुझाव/राय दें या शिकायत करें"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ये सूचनाएं नहीं बदली जा सकती हैं."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉल से जुड़ी सूचनाओं को ब्लॉक नहीं किया जा सकता."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"सूचनाओं के इस समूह को यहां कॉन्फ़िगर नहीं किया जा सकता"</string>
@@ -872,12 +885,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रीन लॉक करने के लिए"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट बनाने के लिए"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टीटास्किंग (एक साथ कई काम करना)"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"स्प्लिट स्क्रीन की सुविधा चालू करें और इस ऐप्लिकेशन को दाईं ओर दिखाएं"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"स्प्लिट स्क्रीन की सुविधा चालू करें और इस ऐप्लिकेशन को बाईं ओर दिखाएं"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"फ़ुल स्क्रीन पर स्विच करें"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन पर, दाईं ओर या नीचे के ऐप पर स्विच करने के लिए"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन पर, बाईं ओर या ऊपर के ऐप पर स्विच करने के लिए"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"स्प्लिट स्क्रीन के दौरान: एक ऐप्लिकेशन को दूसरे ऐप्लिकेशन से बदलें"</string>
@@ -979,7 +989,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेन्यू"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"पेज <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्‍क्रीन"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Find My Device की मदद से, फ़ोन बंद होने पर भी इस फ़ोन की जगह की जानकारी का पता लगाया जा सकता है"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"बंद हो रहा है…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"डिवाइस के रखरखाव के तरीके देखें"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिवाइस के रखरखाव के तरीके देखें"</string>
@@ -1466,22 +1475,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"होम स्क्रीन पर जाएं"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखें"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"हो गया"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"फिर से कोशिश करें!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"वापस जाएं"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"अपने टचपैड पर तीन उंगलियों से बाईं या दाईं ओर स्वाइप करें"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"बढ़िया!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"अब आपको हाथ के जेस्चर का इस्तेमाल करके, पिछली स्क्रीन पर वापस जाने का तरीका पता चल गया है."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"टचपैड का इस्तेमाल करके वापस जाने के लिए, तीन उंगलियों से बाईं या दाईं ओर स्वाइप करें"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होम स्क्रीन पर जाएं"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"बहुत बढ़िया!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"अब आपको हाथ के जेस्चर का इस्तेमाल करके होम स्क्रीन पर जाने का तरीका पता चल गया है"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"होम स्क्रीन पर जाने के लिए, अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखें"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और दबाकर रखें"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"बहुत बढ़िया!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"अब आपको हाथ के जेस्चर का इस्तेमाल करके, हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने का तरीका पता चल गया है."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"हाल ही में इस्तेमाल किए गए ऐप्लिकेशन देखने के लिए, अपने टचपैड पर तीन उंगलियों से ऊपर की ओर स्वाइप करें और दबाकर रखें"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"सभी ऐप्लिकेशन देखें"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"अपने कीबोर्ड पर ऐक्शन बटन दबाएं"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"बहुत खूब!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"अब आपको हाथ के जेस्चर का इस्तेमाल करके, सभी ऐप्लिकेशन देखने का तरीका पता चल गया है"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"सभी ऐप्लिकेशन देखने के लिए, कीबोर्ड पर ऐक्शन बटन दबाएं"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ट्यूटोरियल ऐनिमेशन को रोकने और इन्हें फिर से चलाने के लिए क्लिक करें."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड की बैकलाइट"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d में से %1$d लेवल"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6eabb6a..6fc209fb 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS putem satelita"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nema signala"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"jedna crtica"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dvije crtice"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tri crtice"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"četiri crtice"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"puni signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikazuje se pri vrhu obavijesti razgovora i kao profilna slika na zaključanom zaslonu, izgleda kao oblačić, prekida Ne uznemiravaj"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetno"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava značajke razgovora"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Pošaljite povratne informacije o paketu"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Te se obavijesti ne mogu izmijeniti."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obavijesti o pozivima ne mogu se izmijeniti."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ta se grupa obavijesti ne može konfigurirati ovdje"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje zaslona"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Obavljanje više zadataka"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Upotreba podijeljenog zaslona s aplikacijom s desne strane"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Upotreba podijeljenog zaslona s aplikacijom s lijeve strane"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Prebacivanje na cijeli zaslon"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prelazak na aplikaciju zdesna ili ispod uz podijeljeni zaslon"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prelazak na aplikaciju slijeva ili iznad uz podijeljeni zaslon"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijekom podijeljenog zaslona: zamijeni aplikaciju drugom"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Izbornik tipke za uključivanje/isključivanje"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani zaslon"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Telefon možete pronaći pomoću usluge Pronađi moj uređaj čak i kada je isključen"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Isključivanje…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Pročitajte upute za održavanje"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pročitajte što trebate učiniti"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Na početni zaslon"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Pregled nedavnih aplikacija"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotovo"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Natrag"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Prijeđite ulijevo ili udesno trima prstima na dodirnoj podlozi"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Odlično!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Napravili ste pokret za povratak."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Na početnu stranicu"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Prijeđite prema gore trima prstima na dodirnoj podlozi"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Sjajno!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Napravili ste pokret za otvaranje početnog zaslona"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Pregled nedavnih aplikacija"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Prijeđite prema gore trima prstima na dodirnoj podlozi i zadržite pritisak"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Sjajno!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Napravili ste pokret za prikaz nedavno korištenih aplikacija."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Prikaži sve aplikacije"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipku za radnju na tipkovnici"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Izvrsno!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Napravili ste pokret za prikaz svih aplikacija"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacija u vodiču, kliknite za pauziranje i nastavak reprodukcije."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Pozadinsko osvjetljenje tipkovnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Razina %1$d od %2$d"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2ee7b24..669d596 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Modulok"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"A „Modulok” gyorsparancs hozzáadásához gondoskodjon arról, hogy a „Modulok megjelenítése a lezárási képernyőn” beállítás legyen engedélyezve a beállításokban."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Beállítások"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Képernyőkímélő gomb megjelenítése"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Műholdas SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Segélyhívás vagy SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nincs jel"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"egy sáv"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"két sáv"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"három sáv"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"négy sáv"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"teljes jelerősség"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"A beszélgetésekre vonatkozó értesítések tetején, lebegő buborékként látható, megjeleníti a profilképet a lezárási képernyőn, és megszakítja a Ne zavarjanak funkciót"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritás"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> nem támogatja a beszélgetési funkciókat"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Visszajelzés küldése a csomagról"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ezeket az értesítéseket nem lehet módosítani."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"A hívásértesítéseket nem lehet módosítani."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Az értesítések jelen csoportját itt nem lehet beállítani"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lezárási képernyő"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Jegyzetelés"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Osztott képernyő használata, az alkalmazás a jobb oldalon van"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Osztott képernyő használata, az alkalmazás a bal oldalon van"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Váltás teljes képernyőre"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Váltás a jobb oldalt, illetve lent lévő appra osztott képernyő esetén"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Váltás a bal oldalt, illetve fent lévő appra osztott képernyő esetén"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Osztott képernyőn: az egyik alkalmazás lecserélése egy másikra"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Bekapcsológombhoz tartozó menü"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lezárási képernyő"</string>
-    <string name="finder_active" msgid="7907846989716941952">"A Készülékkereső segítségével akár a kikapcsolt telefon helyét is meghatározhatja."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Leállítás…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Olvassa el a kímélő használat lépéseit"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Olvassa el a kímélő használat lépéseit"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ugrás a főoldalra"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Legutóbbi alkalmazások megtekintése"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kész"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Vissza"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Csúsztassa gyorsan három ujját balra vagy jobbra az érintőpadon."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Remek!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Teljesítette a visszalépési kézmozdulatot."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ugrás a főoldalra"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Csúsztasson gyorsan felfelé három ujjával az érintőpadon."</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Kiváló!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Teljesítette a kezdőképernyőre lépés kézmozdulatát."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Legutóbbi alkalmazások megtekintése"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Csúsztasson gyorsan felfelé három ujjal az érintőpadon, és tartsa rajta lenyomva az ujjait."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Kiváló!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Teljesítette a legutóbbi alkalmazások megtekintésének kézmozdulatát."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Összes alkalmazás megtekintése"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Nyomja meg a műveletbillentyűt az érintőpadon."</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Szép munka!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Teljesítette az összes alkalmazás megtekintésének kézmozdulatát."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Útmutató animáció. Kattintson a szüneteltetéshez és a lejátszás folytatásához."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"A billentyűzet háttérvilágítása"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Fényerő: %2$d/%1$d"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index d43beb8..095c2ad 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Վիջեթներ"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"«Վիջեթներ» դյուրանցումն ավելացնելու համար համոզվեք, որ «Ցույց տալ վիջեթները կողպէկրանին» պարամետրը միացված է կարգավորումներում։"</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Կարգավորումներ"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"«Ցույց տալ էկրանապահը» կոճակ"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Շտապ կանչեր կամ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>։"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ազդանշան չկա"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"մեկ գիծ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"երկու գիծ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"երեք գիծ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"չորս գիծ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ազդանշանը ուժեղ է"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ցուցադրվում է զրույցների ծանուցումների վերևում, ինչպես նաև կողպէկրանին որպես պրոֆիլի նկար, հայտնվում է ամպիկի տեսքով, ընդհատում է «Չանհանգստացնել» ռեժիմը"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Կարևոր"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը զրույցի գործառույթներ չի աջակցում"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Հավաքածուի մասին կարծիք հայտնել"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Այս ծանուցումները չեն կարող փոփոխվել:"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Զանգերի մասին ծանուցումները հնարավոր չէ փոփոխել։"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ծանուցումների տվյալ խումբը հնարավոր չէ կարգավորել այստեղ"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Կողպէկրան"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ստեղծել նշում"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Բազմախնդրու­թյուն"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Տրոհել էկրանը և տեղավորել այս հավելվածը աջ կողմում"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Տրոհել էկրանը և տեղավորել այս հավելվածը ձախ կողմում"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Անցնել լիաէկրան ռեժիմի"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Անցեք աջ կողմի կամ ներքևի հավելվածին տրոհված էկրանի միջոցով"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Անցեք աջ կողմի կամ վերևի հավելվածին տրոհված էկրանի միջոցով"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Տրոհված էկրանի ռեժիմում մեկ հավելվածը փոխարինել մյուսով"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Սնուցման կոճակի ընտրացանկ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Կողպէկրան"</string>
-    <string name="finder_active" msgid="7907846989716941952">"«Գտնել իմ սարքը» ծառայության օգնությամբ դուք կարող եք տեղորոշել այս հեռախոսը, նույնիսկ եթե այն անջատված է"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Անջատվում է…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Քայլեր գերտաքացման ահազանգի դեպքում"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Քայլեր գերտաքացման ահազանգի դեպքում"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ինչպես անցնել հիմնական էկրան"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Դիտել վերջին հավելվածները"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Պատրաստ է"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Հետ գնալ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Հպահարթակի վրա երեք մատով սահեցրեք ձախ կամ աջ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Գերազանց է"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Դուք սովորեցիք հետ գնալու ժեստը։"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Անցում հիմնական էկրան"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Հպահարթակի վրա երեք մատով սահեցրեք վերև"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Կեցցե՛ք"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Դուք սովորեցիք հիմնական էկրան անցնելու ժեստը"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Դիտել վերջին հավելվածները"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Երեք մատով սահեցրեք վերև և սեղմած պահեք հպահարթակին"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Կեցցե՛ք"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Դուք կատարեցիք վերջին օգտագործված հավելվածների դիտման ժեստը։"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ինչպես դիտել բոլոր հավելվածները"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Սեղմեք գործողության ստեղնը ստեղնաշարի վրա"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Հիանալի՛ է"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Դուք սովորեցիք բոլոր հավելվածները դիտելու ժեստը"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Ուղեցույցի անիմացիա․ սեղմեք՝ նվագարկումը դադարեցնելու/վերսկսելու համար։"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Հետին լուսավորությամբ ստեղնաշար"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d՝ %2$d-ից"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 095b35b..b5b5888 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Untuk menambahkan pintasan \"Widget\", pastikan \"Tampilkan widget di layar kunci\" diaktifkan di setelan."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Setelan"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Tampilkan tombol screensaver"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan darurat atau SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"tidak ada sinyal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"satu batang"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dua batang"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tiga batang"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"empat batang"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinyal penuh"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Muncul teratas di notifikasi percakapan dan sebagai foto profil di layar kunci, ditampilkan sebagai balon, menimpa mode Jangan Ganggu"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritas"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung fitur percakapan"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Berikan Masukan Gabungan"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Notifikasi ini tidak dapat diubah."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notifikasi panggilan tidak dapat diubah."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Grup notifikasi ini tidak dapat dikonfigurasi di sini"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci layar"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Buat catatan"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Gunakan layar terpisah dengan aplikasi di sebelah kanan"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Gunakan layar terpisah dengan aplikasi di sebelah kiri"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Beralih ke layar penuh"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Beralih ke aplikasi di bagian kanan atau bawah saat menggunakan layar terpisah"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Beralih ke aplikasi di bagian kiri atau atas saat menggunakan layar terpisah"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Dalam layar terpisah: ganti salah satu aplikasi dengan yang lain"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu daya"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Layar kunci"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Anda dapat menemukan lokasi ponsel ini dengan Temukan Perangkat Saya meskipun ponsel dimatikan"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Sedang mematikan…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Lihat langkah-langkah perawatan"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Lihat langkah-langkah perawatan"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Buka layar utama"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Lihat aplikasi terbaru"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Geser ke kiri atau kanan menggunakan tiga jari di touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Sip!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Anda telah menyelesaikan gestur untuk kembali."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Buka layar utama"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Geser ke atas dengan tiga jari di touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bagus!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Anda telah menyelesaikan gestur buka layar utama"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Lihat aplikasi terbaru"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Geser ke atas dan tahan menggunakan tiga jari di touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bagus!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda telah menyelesaikan gestur untuk melihat aplikasi terbaru."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Lihat semua aplikasi"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tekan tombol tindakan di keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Oke!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Anda telah menyelesaikan gestur untuk melihat semua aplikasi"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animasi tutorial, klik untuk menjeda dan melanjutkan pemutaran."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Lampu latar keyboard"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tingkat %1$d dari %2$d"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 8a885f0..a1ad51e 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Gervihnattar-SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Neyðarsímtöl eða SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ekkert samband"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"eitt strik"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"tvö strik"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"þrjú strik"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"fjögur strik"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"fullt samband"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Birtist efst í samtalstilkynningum og sem prófílmynd á lásskjánum. Birtist sem blaðra sem truflar „Ónáðið ekki“"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Forgangur"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> styður ekki samtalseiginleika"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Senda inn ábendingu um pakka"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ekki er hægt að breyta þessum tilkynningum."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Ekki er hægt að breyta tilkynningum um símtöl."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ekki er hægt að stilla þessar tilkynningar hér"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lásskjár"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Skrifa glósu"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Fjölvinnsla"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Notaðu skjáskiptingu fyrir forritið til hægri"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Notaðu skjáskiptingu fyrir forritið til vinstri"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Skipta yfir í allan skjáinn"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Skiptu í forrit til hægri eða fyrir neðan þegar skjáskipting er notuð"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Skiptu í forrit til vinstri eða fyrir ofan þegar skjáskipting er notuð"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Í skjáskiptingu: Skipta forriti út fyrir annað forrit"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aflrofavalmynd"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lásskjár"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Þú getur fundið þennan síma með „Finna tækið mitt“, jafnvel þótt slökkt sé á honum"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Slekkur…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Sjá varúðarskref"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sjá varúðarskref"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Fara á heimaskjá"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Sjá nýleg forrit"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Lokið"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Til baka"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Strjúktu til hægri eða vinstri á snertifletinum með þremur fingrum"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Flott!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Þú laukst við að kynna þér bendinguna „til baka“."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Heim"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Strjúktu upp á snertifletinum með þremur fingrum"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Vel gert!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Þú framkvæmdir bendinguna „Fara á heimaskjá“"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Sjá nýleg forrit"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Strjúktu upp og haltu þremur fingrum inni á snertifletinum."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Vel gert!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Þú framkvæmdir bendinguna til að sjá nýleg forrit."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Sjá öll forrit"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Ýttu á aðgerðalykilinn á lyklaborðinu"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Vel gert!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Þú framkvæmdir bendinguna „Sjá öll forrit“"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Leiðsagnarhreyfimynd, smelltu til að gera hlé og halda áfram að spila."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Baklýsing lyklaborðs"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stig %1$d af %2$d"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 790a80d..03a6f54 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -704,7 +704,7 @@
     <string name="volume_panel_spatial_audio_title" msgid="3367048857932040660">"Audio spaziale"</string>
     <string name="volume_panel_spatial_audio_off" msgid="4177490084606772989">"Off"</string>
     <string name="volume_panel_spatial_audio_fixed" msgid="3136080137827746046">"Fisso"</string>
-    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Rilev. movim. testa"</string>
+    <string name="volume_panel_spatial_audio_tracking" msgid="5711115234001762974">"Tracciamento testa"</string>
     <string name="volume_ringer_change" msgid="3574969197796055532">"Tocca per cambiare la modalità della suoneria"</string>
     <string name="volume_ringer_mode" msgid="6867838048430807128">"modalità suoneria"</string>
     <string name="volume_ringer_drawer_closed_content_description" msgid="4737792429808781745">"<xliff:g id="VOLUME_RINGER_STATUS">%1$s</xliff:g>, tocca per cambiare la modalità della suoneria"</string>
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satellitare"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chiamate di emergenza o SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nessun segnale"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"una barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"due barre"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tre barre"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"quattro barre"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"massimo segnale"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Appare in cima alle notifiche delle conversazioni, come immagine del profilo nella schermata di blocco e sotto forma di bolla, inoltre interrompe la modalità Non disturbare"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le funzionalità delle conversazioni"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Fornisci feedback sul bundle"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossibile modificare queste notifiche."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Impossibile modificare gli avvisi di chiamata."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Qui non è possibile configurare questo gruppo di notifiche"</string>
@@ -976,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu del tasto di accensione"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Schermata di blocco"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Puoi trovare questo smartphone tramite Trova il mio dispositivo anche quando è spento"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Arresto in corso…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Leggi le misure da adottare"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Leggi le misure da adottare"</string>
@@ -1463,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Vai alla schermata Home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Visualizza app recenti"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Fine"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Indietro"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Scorri verso sinistra o destra con tre dita sul touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bene!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Hai completato il gesto Indietro."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Vai alla schermata Home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Scorri in alto con tre dita sul touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Ottimo lavoro!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Hai completato il gesto Vai alla schermata Home"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Visualizza app recenti"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Scorri verso l\'alto e tieni premuto con tre dita sul touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Ottimo lavoro!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Hai completato il gesto Visualizza app recenti."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Visualizza tutte le app"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Premi il tasto azione sulla tastiera"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Ben fatto!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Hai completato il gesto Visualizza tutte le app."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animazione del tutorial: fai clic per mettere in pausa e riprendere la riproduzione."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Retroilluminazione della tastiera"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Livello %1$d di %2$d"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 99939a8..1d74a49 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ווידג\'טים"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"כדי להוסיף את קיצור הדרך \"ווידג\'טים\", צריך לוודא שהאפשרות \"ווידג\'טים במסך הנעילה\" מופעלת בהגדרות."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"הגדרות"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"לחצן להצגת שומר המסך"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"תקשורת לוויינית למצב חירום"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"‏שיחות חירום או SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"‫<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"אין קליטה"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"פס אחד"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"שני פסים"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"שלושה פסים"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ארבעה פסים"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"קליטה מלאה"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"מוצגת בחלק העליון של קטע התראות השיחה וכתמונת פרופיל במסך הנעילה, מופיעה בבועה צפה ומפריעה במצב \'נא לא להפריע\'"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"בעדיפות גבוהה"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"האפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לא תומכת בתכונות השיחה"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"שליחת משוב על החבילה"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"לא ניתן לשנות את ההתראות האלה."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"לא ניתן לשנות את התראות השיחה."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"לא ניתן להגדיר כאן את קבוצת ההתראות הזו"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"נעילת המסך"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"כתיבת הערה"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ריבוי משימות"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"שימוש במסך מפוצל כשהאפליקציה בצד ימין"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"שימוש במסך מפוצל כשהאפליקציה בצד שמאל"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"למסך מלא"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"מעבר לאפליקציה משמאל או למטה בזמן שימוש במסך מפוצל"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"מעבר לאפליקציה מימין או למעלה בזמן שימוש במסך מפוצל"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"כשהמסך מפוצל: החלפה בין אפליקציה אחת לאחרת"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"תפריט הפעלה"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"מסך נעילה"</string>
-    <string name="finder_active" msgid="7907846989716941952">"אפשר לאתר את הטלפון הזה עם שירות \'איפה המכשיר שלי\' גם כשהוא כבוי"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"בתהליך כיבוי…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"לצפייה בשלבי הטיפול"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"לצפייה בשלבי הטיפול"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"חזרה לדף הבית"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"הצגת האפליקציות האחרונות"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"סיום"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"חזרה"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"מחליקים שמאלה או ימינה עם שלוש אצבעות על לוח המגע"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"איזה יופי!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"סיימת לתרגל את התנועה \'הקודם\'."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"מעבר למסך הבית"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"מחליקים כלפי מעלה עם שלוש אצבעות על לוח המגע"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"מעולה!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"סיימת לתרגל את תנועת החזרה למסך הבית"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"הצגת האפליקציות האחרונות"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"מחליקים למעלה עם שלוש אצבעות על לוח המגע ומשאירים אותן במגע עם הלוח"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"מעולה!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"סיימת לתרגל את התנועה להצגת האפליקציות האחרונות."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"צפייה בכל האפליקציות"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"צריך להקיש על מקש הפעולה במקלדת"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"כל הכבוד!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"סיימת לתרגל את התנועה להצגת כל האפליקציות"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"אנימציה של הדרכה, אפשר ללחוץ כדי להשהות ולהמשיך את ההפעלה."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"התאורה האחורית במקלדת"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏רמה %1$d מתוך %2$d"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 5fd029b2..da74e23 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"衛星 SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急通報または SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>、<xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>。"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"圏外"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"レベル 1"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"レベル 2"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"レベル 3"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"レベル 4"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"電波フル"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"会話通知の一番上に表示されると同時に、ロック画面にプロフィール写真として表示されるほか、バブルとして表示され、サイレント モードが中断されます"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>は会話機能に対応していません"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"バンドルに関するフィードバックを送信"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"これらの通知は変更できません。"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"着信通知は変更できません。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"このグループの通知はここでは設定できません"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"画面をロック"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"メモを入力する"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"マルチタスク"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"分割画面の使用(アプリを右側に表示)"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"分割画面の使用(アプリを左側に表示)"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"全画面表示に切り替える"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"分割画面の使用時に右側または下部のアプリに切り替える"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"分割画面の使用時に左側または上部のアプリに切り替える"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"分割画面中: アプリを順に置換する"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源ボタン メニュー"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ページ <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ロック画面"</string>
-    <string name="finder_active" msgid="7907846989716941952">"「デバイスを探す」を使うと、電源が OFF の状態でもこのスマートフォンの現在地を確認できます"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"シャットダウン中…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"取り扱いに関する手順をご覧ください"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"取り扱いに関する手順をご覧ください"</string>
@@ -1275,7 +1277,7 @@
     <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"タップすると詳細が表示されます"</string>
     <string name="qs_alarm_tile_no_alarm" msgid="4826472008616807923">"アラーム未設定"</string>
     <string name="accessibility_bouncer" msgid="5896923685673320070">"画面ロックを設定"</string>
-    <string name="accessibility_side_fingerprint_indicator_label" msgid="1673807833352363712">"指紋認証センサーに触れてください。スマートフォンの側面にある高さが低い方のボタンです。"</string>
+    <string name="accessibility_side_fingerprint_indicator_label" msgid="1673807833352363712">"指紋認証センサーに触れてください。スマートフォンの側面にあるボタンのうち、上側の短いボタンです。"</string>
     <string name="accessibility_fingerprint_label" msgid="5255731221854153660">"指紋認証センサー"</string>
     <string name="accessibility_authenticate_hint" msgid="798914151813205721">"認証"</string>
     <string name="accessibility_enter_hint" msgid="2617864063504824834">"デバイスを入力"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ホームに移動"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"最近使ったアプリを表示する"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完了"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"もう一度お試しください。"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"戻る"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"タッチパッドを 3 本の指で左または右にスワイプします"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"その調子です!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"「戻る」ジェスチャーを学習しました。"</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"タッチパッドを使用して戻るには、3 本の指で左または右にスワイプします"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ホームに移動"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"タッチパッドを 3 本の指で上にスワイプします"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"よくできました!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"「ホームに移動」ジェスチャーを学習しました"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"ホーム画面に移動するには、タッチパッドを 3 本の指で上にスワイプします"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"最近使ったアプリを表示する"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"タッチパッドを 3 本の指で上にスワイプして長押しします"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"よくできました!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"「最近使ったアプリを表示する」ジェスチャーを学習しました。"</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"最近使ったアプリを表示するには、3 本の指でタッチパッドを上にスワイプして長押しします"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"すべてのアプリを表示"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"キーボードのアクションキーを押します"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"完了です!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"「すべてのアプリを表示する」ジェスチャーを学習しました"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"すべてのアプリを表示するには、キーボードのアクションキーを押します"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"チュートリアルのアニメーションです。クリックすると一時停止、もう一度クリックすると再開します。"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"キーボード バックライト"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"レベル %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 55d38c9..5a20158 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"სატელიტური SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"გადაუდებელი ზარი ან SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"სიგნალი არ არის"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ერთი ხაზი"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ორი ხაზი"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"სამი ხაზი"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ოთხი ხაზი"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"სრული სიგნალი"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"გამოჩნდება საუბრის შეტყობინებების თავში და პროფილის სურათის სახით ჩაკეტილ ეკრანზე, ჩნდება ბუშტის სახით, წყვეტს ფუნქციას „არ შემაწუხოთ“"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"პრიორიტეტი"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს არ აქვს მიმოწერის ფუნქციების მხარდაჭერა"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ნაკრებზე გამოხმაურების წარმოდგენა"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ამ შეტყობინებების შეცვლა შეუძლებელია."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ზარის შეტყობინებების შეცვლა შეუძლებელია."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"შეტყობინებების ამ ჯგუფის კონფიგურირება აქ შეუძლებელია"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ჩაკეტილი ეკრანი"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ჩაინიშნეთ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"მრავალამოცანიანი რეჟიმი"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ეკრანის გაყოფის გამოყენება აპზე მარჯვნივ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ეკრანის გაყოფის გამოყენება აპზე მარცხნივ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"სრულ ეკრანზე გადართვა"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ეკრანის გაყოფის გამოყენებისას აპზე მარჯვნივ ან ქვემოთ გადართვა"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ეკრანის გაყოფის გამოყენებისას აპზე მარცხნივ ან ზემოთ გადართვა"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ეკრანის გაყოფის დროს: ერთი აპის მეორით ჩანაცვლება"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ჩართვის მენიუ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ჩაკეტილი ეკრანი"</string>
-    <string name="finder_active" msgid="7907846989716941952">"შეგიძლიათ დაადგინოთ ამ ტელეფონის მდებარეობა ფუნქციით „ჩემი მოწყობილობის პოვნა“, მაშინაც კი, როდესაც ის გამორთულია"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"მიმდინარეობს გამორთვა…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"მისაღები ზომების გაცნობა"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"მისაღები ზომების გაცნობა"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"მთავარ ეკრანზე გადასვლა"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ბოლო აპების ნახვა"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"მზადაა"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"ცადეთ ხელახლა!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"უკან დაბრუნება"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ მარცხნივ ან მარჯვნივ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"მშვენიერია!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"თქვენ შეასრულეთ უკან დაბრუნების ჟესტი."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"თქვენი სენსორული პანელის კვლავ გამოსაყენებლად გადაფურცლეთ მარცხნივ ან მარჯვნივ სამი თითით"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"მთავარზე გადასვლა"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"შესანიშნავია!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"თქვენ შეასრულეთ მთავარ ეკრანზე გადასვლის ჟესტი"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით მთავარ ეკრანზე გადასავლელად"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ბოლო აპების ნახვა"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით და ხანგრძლივად დააჭირეთ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"შესანიშნავია!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"თქვენ დაასრულეთ ბოლო აპების ხედის ჟესტი."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ბოლო აპების სანახავად თქვენს სენსორულ პანელზე სამი თითით გადაფურცლეთ ზევით და ხანგრძლივად დააჭირეთ"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ყველა აპის ნახვა"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ყოჩაღ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"თქვენ დაასრულეთ ყველა აპის ნახვის ჟესტი"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"დააჭირეთ მოქმედების კლავიშს თქვენს კლავიატურაზე ყველა თქვენი აპის სანახავად"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"სახელმძღვანელო ანიმაცია, დააწკაპუნეთ დასაპაუზებლად და გასაგრძელებლად."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"კლავიატურის შენათება"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"დონე: %1$d %2$d-დან"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 9b6dc95..5bd63b1 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеттер"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджеттер\" таңбашасын қосу үшін параметрлерде \"Виджеттерді құлыптаулы экранда көрсету\" опциясының қосулы екенін тексеріңіз."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Параметрлер"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Скринсейвер түймесін көрсету"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Құтқару қызметіне қоңырау шалу немесе SOS сигналын жіберу"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"сигнал жоқ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"бір жолақ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"екі жолақ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"үш жолақ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"төрт жолақ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"толық сигнал"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Әңгіме туралы хабарландырулардың жоғарғы жағында тұрады және құлыптаулы экранда профиль суреті болып көрсетіледі, қалқыма хабар түрінде шығады, Мазаламау режимін тоқтатады."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгіме функцияларын қолдамайды."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Пакет туралы пікір жіберу"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Қоңырау туралы хабарландыруларды өзгерту мүмкін емес."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды құлыптау"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ескертпе жазу"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мультитаскинг"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Қолданбаны бөлінген экранның оң жағынан пайдалану"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Қолданбаны бөлінген экранның сол жағынан пайдалану"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Толық экранға ауысу"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлінген экранда оң не төмен жақтағы қолданбаға ауысу"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлінген экранда сол не жоғары жақтағы қолданбаға ауысу"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Экранды бөлу кезінде: бір қолданбаны басқасымен алмастыру"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Қуат мәзірі"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Құлыптаулы экран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Сіз бұл телефонды, ол тіпті өшірулі тұрса да Find My Device арқылы таба аласыз."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Өшіріліп жатыр…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Пайдалану нұсқаулығын қараңыз"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Пайдалану нұсқаулығын қараңыз"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Негізгі бетке өту"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Соңғы қолданбаларды көру"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Дайын"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артқа"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Сенсорлық тақтада үш саусақпен оңға немесе солға сырғытыңыз."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Керемет!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Артқа қайту қимылын аяқтадыңыз."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Негізгі экранға өту"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Сенсорлық тақтада үш саусақпен жоғары сырғытыңыз."</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Жарайсыз!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Негізгі экранға қайту қимылын орындадыңыз."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Соңғы қолданбаларды көру"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Сенсорлық тақтада үш саусақпен жоғары сырғытып, басып тұрыңыз."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Жарайсыз!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Соңғы қолданбаларды көру қимылын орындадыңыз."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Барлық қолданбаны көру"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Пернетақтадағы әрекет пернесін басыңыз."</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Жарайсыз!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Барлық қолданбаны көру қимылын орындадыңыз."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Оқулықтың анимациясы, ойнатуды кідірту және жалғастыру үшін басыңыз."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Пернетақта жарығы"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Деңгей: %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 50f5fa0..fa3fc664 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ការប្រកាសអាសន្នតាមផ្កាយរណប"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់ ឬ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>។"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"គ្មានសញ្ញា"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"មួយកាំ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ពីរកាំ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"បីកាំ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"បួនកាំ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"សញ្ញាពេញ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"បង្ហាញនៅខាងលើ​ការជូនដំណឹងអំពីការសន្ទនា និងជារូបភាព​កម្រង​ព័ត៌មាននៅលើអេក្រង់ចាក់សោ បង្ហាញជាពពុះ បង្អាក់មុខងារកុំ​រំខាន"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"អាទិភាព"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនអាចប្រើ​មុខងារ​សន្ទនា​បានទេ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ផ្ដល់មតិកែលម្អជាកញ្ចប់"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"មិនអាច​កែប្រែ​ការជូនដំណឹង​ទាំងនេះ​បានទេ។"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"មិនអាច​កែប្រែ​ការជូនដំណឹងអំពីការហៅទូរសព្ទបានទេ។"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"មិនអាច​កំណត់​រចនាសម្ព័ន្ធ​ក្រុមការជូនដំណឹងនេះ​នៅទីនេះ​បានទេ"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ចាក់​សោ​អេក្រង់"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"កត់​ចំណាំ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ការដំណើរការបានច្រើន"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីនៅខាងស្ដាំ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ប្រើមុខងារបំបែកអេក្រង់ជាមួយកម្មវិធីនៅខាងឆ្វេង"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ប្ដូរទៅ​អេក្រង់ពេញ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ប្ដូរទៅកម្មវិធីនៅខាងស្ដាំ ឬខាងក្រោម ពេលកំពុងប្រើមុខងារ​បំបែកអេក្រង់"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ប្ដូរទៅកម្មវិធីនៅខាងឆ្វេង ឬខាងលើ ពេលកំពុងប្រើមុខងារ​បំបែកអេក្រង់"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ក្នុងអំឡុងពេលប្រើមុខងារបំបែកអេក្រង់៖ ជំនួសកម្មវិធីពីមួយទៅមួយទៀត"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ម៉ឺនុយ​ថាមពល"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"អេក្រង់​ចាក់សោ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"អ្នកអាចកំណត់ទីតាំងទូរសព្ទនេះដោយប្រើ \"រកឧបករណ៍របស់ខ្ញុំ\" សូម្បីនៅពេលបិទថាមពល"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"កំពុង​បិទ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"មើលជំហាន​ថែទាំ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"មើលជំហាន​ថែទាំ"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ទៅទំព័រដើម"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"មើលកម្មវិធីថ្មីៗ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"រួចរាល់"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"សូមព្យាយាមម្ដងទៀត!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ថយ​ក្រោយ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"អូសទៅឆ្វេង ឬស្ដាំដោយប្រើ​ម្រាមដៃបីនៅលើផ្ទាំងប៉ះរបស់អ្នក"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ល្អ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"អ្នក​បានបញ្ចប់​ចលនា​ថយក្រោយ​ហើយ។"</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"ដើម្បីត្រឡប់ក្រោយដោយប្រើផ្ទាំងប៉ះរបស់អ្នក សូមអូសទៅឆ្វេង ឬស្ដាំដោយប្រើម្រាមដៃបី"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ទៅទំព័រដើម"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"អូសឡើងលើដោយប្រើម្រាមដៃបី​នៅលើផ្ទាំងប៉ះរបស់អ្នក"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ធ្វើបានល្អ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"អ្នក​បានបញ្ចប់​ចលនា​ចូលទៅកាន់​ទំព័រដើម​ហើយ"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"អូសឡើងលើដោយប្រើម្រាមដៃបីលើផ្ទាំងប៉ះរបស់អ្នក ដើម្បីទៅកាន់អេក្រង់ដើមរបស់អ្នក"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"មើលកម្មវិធីថ្មីៗ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"អូសឡើងលើ ហើយសង្កត់ឱ្យជាប់ដោយប្រើម្រាមដៃបីលើផ្ទាំងប៉ះរបស់អ្នក"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ធ្វើបានល្អ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"អ្នកបានបញ្ចប់ការមើលចលនាកម្មវិធីថ្មីៗ។"</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ដើម្បីមើលកម្មវិធីថ្មីៗ សូមអូសឡើងលើ រួចសង្កត់ឱ្យជាប់លើផ្ទាំងប៉ះរបស់អ្នក ដោយប្រើម្រាមដៃបី"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"មើល​កម្មវិធី​ទាំងអស់"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ចុចគ្រាប់ចុចសកម្មភាពលើក្ដារចុចរបស់អ្នក"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ធ្វើបាន​ល្អ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"អ្នកបានបញ្ចប់ចលនាមើលកម្មវិធីទាំងអស់ហើយ"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"ចុចគ្រាប់ចុចសកម្មភាពលើក្ដារចុចរបស់អ្នក ដើម្បីមើលកម្មវិធីទាំងអស់របស់អ្នក"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"រូបមានចលនាក្នុងអំឡុងមេរៀន ចុចដើម្បីផ្អាក រួចបន្តការចាក់ឡើងវិញ។"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ពន្លឺក្រោយក្ដារចុច"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"កម្រិតទី %1$d នៃ %2$d"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index a3718d3..e53988c 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ಸ್ಯಾಟಲೈಟ್ SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ತುರ್ತು ಕರೆಗಳು ಅಥವಾ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ಸಿಗ್ನಲ್ ಇಲ್ಲ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ಒಂದು ಬಾರ್"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ಎರಡು ಬಾರ್‌ಗಳು"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"ಮೂರು ಬಾರ್‌ಗಳು"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ನಾಲ್ಕು ಬಾರ್‌ಗಳು"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ಸಿಗ್ನಲ್‌‌ ಪೂರ್ತಿ ಇದೆ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ಸಂಭಾಷಣೆ ಅಧಿಸೂಚನೆಗಳ ಮೇಲ್ಭಾಗದಲ್ಲಿ ಹಾಗೂ ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನ ಮೇಲೆ ಪ್ರೊಫೈಲ್ ಚಿತ್ರವಾಗಿ ತೋರಿಸುತ್ತದೆ, ಬಬಲ್‌ನಂತೆ ಗೋಚರಿಸುತ್ತದೆ, ಅಡಚಣೆ ಮಾಡಬೇಡ ಮೋಡ್‌ಗೆ ಅಡ್ಡಿಯುಂಟುಮಾಡುತ್ತದೆ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ಆದ್ಯತೆ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"ಸಂವಾದ ಫೀಚರ್‌ಗಳನ್ನು <xliff:g id="APP_NAME">%1$s</xliff:g> ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ಬಂಡಲ್‌ ಫೀಡ್‌ಬ್ಯಾಕ್‌ ಅನ್ನು ಒದಗಿಸಿ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ಕರೆ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ಈ ಗುಂಪಿನ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇಲ್ಲಿ ಕಾನ್ಫಿಗರ್‌ ಮಾಡಲಾಗಿರುವುದಿಲ್ಲ"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ಟಿಪ್ಪಣಿಯನ್ನು ತೆಗೆದುಕೊಳ್ಳಿ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ಮಲ್ಟಿಟಾಸ್ಕಿಂಗ್"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ಬಲಭಾಗದಲ್ಲಿ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ಎಡಭಾಗದಲ್ಲಿ ಆ್ಯಪ್ ಮೂಲಕ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಬಳಸಿ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ಫುಲ್‌ಸ್ಕ್ರೀನ್ ಮೋಡ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಬಲಭಾಗ ಅಥವಾ ಕೆಳಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸಿ ಮೋಡ್ ಬಳಸುವಾಗ ಎಡಭಾಗ ಅಥವಾ ಮೇಲ್ಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಿ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ಸ್ಕ್ರೀನ್ ಬೇರ್ಪಡಿಸುವ ಸಮಯದಲ್ಲಿ: ಒಂದು ಆ್ಯಪ್‌ನಿಂದ ಮತ್ತೊಂದು ಆ್ಯಪ್‌ಗೆ ಬದಲಿಸಿ"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ಪವರ್ ಮೆನು"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ಪವರ್ ಆಫ್ ಆಗಿರುವಾಗಲೂ ನೀವು Find My Device ಮೂಲಕ ಈ ಫೋನ್ ಅನ್ನು ಪತ್ತೆ ಮಾಡಬಹುದು"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ಶಟ್ ಡೌನ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
@@ -1466,23 +1468,33 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಿ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ಮುಗಿದಿದೆ"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ಹಿಂತಿರುಗಿ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ನಿಮ್ಮ ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಎಡ ಅಥವಾ ಬಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ಚೆನ್ನಾಗಿದೆ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ನೀವು ಗೋ ಬ್ಯಾಕ್ ಗೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ಮುಖಪುಟಕ್ಕೆ ಹೋಗಿ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ಮೂರು ಬೆರಳಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ಭೇಷ್!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ನೀವು ಗೋ ಹೋಮ್ ಜೆಸ್ಚರ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ಇತ್ತೀಚಿನ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ನಿಮ್ಮ ಟಚ್‌ಪ್ಯಾಡ್‌ನಲ್ಲಿ ಮೂರು ಬೆರಳುಗಳನ್ನು ಬಳಸಿ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ಭೇಷ್‌!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ನೀವು ಇತ್ತೀಚಿನ ಆ್ಯಪ್‌ಗಳ ಜೆಸ್ಚರ್‌ ವೀಕ್ಷಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ನಿಮ್ಮ ಕೀಬೋರ್ಡ್‌ನಲ್ಲಿ ಆ್ಯಕ್ಷನ್‌ ಕೀಯನ್ನು ಒತ್ತಿ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ಭೇಷ್!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ನೀವು ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳ ಜೆಸ್ಚರ್‌ ವೀಕ್ಷಣೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಿದ್ದೀರಿ"</string>
-    <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ಟ್ಯುಟೋರಿಯಲ್ ಅನಿಮೇಷನ್, ವಿರಾಮಗೊಳಿಸಲು ಮತ್ತು ಪ್ಲೇ ಪುನರಾರಂಭಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
+    <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ಟುಟೋರಿಯಲ್ ಆ್ಯನಿಮೇಷನ್, ವಿರಾಮಗೊಳಿಸಲು ಮತ್ತು ಪ್ಲೇ ಪುನರಾರಂಭಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ಕೀಬೋರ್ಡ್ ಬ್ಯಾಕ್‌ಲೈಟ್"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ರಲ್ಲಿ %1$d ಮಟ್ಟ"</string>
     <string name="home_controls_dream_label" msgid="6567105701292324257">"ಮನೆ ನಿಯಂತ್ರಣಗಳು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ee19ad2..dc6fcda 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"위젯"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\'위젯\' 바로가기를 추가하려면 설정에서 \'잠금 화면에 위젯 표시\'가 사용 설정되어 있어야 합니다."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"설정"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"화면 보호기 버튼 표시"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"위성 긴급 SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"긴급 전화 또는 SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"신호가 없습니다"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"신호 막대가 1개입니다"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"신호 막대가 2개입니다"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"신호 막대가 3개입니다"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"신호 막대가 4개입니다"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"신호가 강합니다"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"대화 알림 상단에 표시, 잠금 화면에 프로필 사진으로 표시, 대화창으로 표시, 방해 금지 모드를 무시함"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 대화 기능을 지원하지 않습니다."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"번들 관련 의견 보내기"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"이 알림은 수정할 수 없습니다."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"전화 알림은 수정할 수 없습니다."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"이 알림 그룹은 여기에서 설정할 수 없습니다."</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"메모 작성"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"멀티태스킹"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"앱이 오른쪽에 오도록 화면 분할 사용"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"앱이 왼쪽에 오도록 화면 분할 사용"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"전체 화면으로 전환"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"화면 분할을 사용하는 중에 오른쪽 또는 아래쪽에 있는 앱으로 전환"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"화면 분할을 사용하는 중에 왼쪽 또는 위쪽에 있는 앱으로 전환하기"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"화면 분할 중: 다른 앱으로 바꾸기"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"전원 메뉴"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"잠금 화면"</string>
-    <string name="finder_active" msgid="7907846989716941952">"전원이 꺼져 있을 때도 내 기기 찾기로 이 휴대전화를 찾을 수 있습니다."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"종료 중…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"해결 방법 확인하기"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"해결 방법 확인하기"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"홈으로 이동"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"최근 앱 보기"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"완료"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"뒤로"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"세 손가락을 사용해 터치패드에서 왼쪽 또는 오른쪽으로 스와이프하세요."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"훌륭합니다"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"돌아가기 동작을 완료했습니다."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"홈으로 이동"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"세 손가락을 사용해 터치패드에서 위로 스와이프하세요."</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"잘하셨습니다"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"홈으로 이동 동작을 완료했습니다."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"최근 앱 보기"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"세 손가락을 사용해 터치패드에서 위로 스와이프한 후 잠시 기다리세요."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"아주 좋습니다"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"최근 앱 보기 동작을 완료했습니다."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"모든 앱 보기"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"키보드의 작업 키를 누르세요."</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"잘하셨습니다"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"모든 앱 보기 동작을 완료했습니다."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"튜토리얼 애니메이션입니다. 일시중지하고 재생을 재개하려면 클릭하세요."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"키보드 백라이트"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d단계 중 %1$d단계"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 7ebfdec..83ec250 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеттер"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджеттер\" ыкчам баскычын кошуу үчүн параметрлерге өтүп, \"Виджеттерди кулпуланган экранда көрсөтүү\" параметри иштетилгенин текшериңиз."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Параметрлер"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Көшөгө баскычын көрсөтүү"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутник SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Шашылыш чалуулар же SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"сигнал жок"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"бир мамыча"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"эки мамыча"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"үч мамыча"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"төрт мамыча"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"толук сигнал"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Cүйлөшүүлөр тууралуу билдирмелердин жогору жагында жана кулпуланган экранда профилдин сүрөтү, ошондой эле калкып чыкма билдирме түрүндө көрүнүп, \"Тынчымды алба\" режимин токтотот"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Маанилүүлүгү"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосунда оозеки сүйлөшкөнгө болбойт"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Топтом тууралуу пикир билдирүү"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Бул билдирмелерди өзгөртүүгө болбойт."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Чалуу билдирмелерин өзгөртүүгө болбойт."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Бул билдирмелердин тобун бул жерде конфигурациялоого болбойт"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Экранды кулпулоо"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Кыска жазуу түзүү"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Бир нече тапшырма аткаруу"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Колдонмону оңго жылдырып, экранды бөлүү"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Колдонмону солго жылдырып, экранды бөлүү"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Толук экранга которулуу"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Бөлүнгөн экранда сол же төмөн жактагы колдонмого которулуу"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Бөлүнгөн экранды колдонуп жатканда сол же жогору жактагы колдонмого которулуңуз"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Экранды бөлүү режиминде бир колдонмону экинчисине алмаштыруу"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Кубат баскычынын менюсу"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Кулпуланган экран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Бул телефон өчүк болсо да, аны \"Түзмөгүм кайда?\" кызматы аркылуу таба аласыз"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Өчүрүлүүдө…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Тейлөө кадамдарын көрүңүз"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Тейлөө кадамдарын көрүңүз"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Башкы бетке өтүү"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Акыркы колдонмолорду көрүү"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Бүттү"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Артка кайтуу"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Сенсордук тактаны үч манжаңыз менен солго же оңго сүрүңүз"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Сонун!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"\"Артка\" жаңсоосун үйрөндүңүз."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Башкы бетке өтүү"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Сенсордук тактаны үч манжаңыз менен жогору сүрүңүз"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Азаматсыз!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"\"Башкы бетке өтүү\" жаңсоосун үйрөндүңүз"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Акыркы колдонмолорду көрүү"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Сенсордук тактаны үч манжаңыз менен өйдө сүрүп, кармап туруңуз"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Азаматсыз!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Акыркы колдонмолорду көрүү жаңсоосун аткардыңыз."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Бардык колдонмолорду көрүү"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Баскычтобуңуздагы аракет баскычын басыңыз"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Эң жакшы!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Бардык колдонмолорду көрүү жаңсоосун аткардыңыз"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Үйрөткүч анимация, ойнотууну тындыруу же улантуу үчүн чыкылдатыңыз."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Баскычтоптун жарыгы"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ичинен %1$d-деңгээл"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 151687f..53d3bca 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ດາວທຽມ"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ໂທສຸກເສີນ ຫຼື SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ບໍ່ມີສັນຍານ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 ຂີດ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 ຂີດ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 ຂີດ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 ຂີດ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ສັນຍານເຕັມ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ສະແດງຢູ່ເທິງສຸດຂອງການແຈ້ງເຕືອນການສົນທະນາ ແລະ ເປັນຮູບໂປຣໄຟລ໌ຢູ່ໜ້າຈໍລັອກ, ປາກົດເປັນຟອງ, ສະແດງໃນໂໝດຫ້າມລົບກວນໄດ້"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ສຳຄັນ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ຮອງຮັບຄຸນສົມບັດການສົນທະນາ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ໃຫ້ຄຳຕິຊົມເປັນຊຸດ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ບໍ່ສາມາດແກ້ໄຂການແຈ້ງເຕືອນການໂທໄດ້."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ບໍ່ສາມາດຕັ້ງຄ່າກຸ່ມການແຈ້ງເຕືອນນີ້ຢູ່ບ່ອນນີ້ໄດ້"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ໜ້າຈໍລັອກ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ຈົດບັນທຶກ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ການເຮັດຫຼາຍໜ້າວຽກພ້ອມກັນ"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ໃຊ້ໂໝດແບ່ງໜ້າຈໍໂດຍໃຫ້ແອັບຢູ່ເບື້ອງຂວາ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ໃຊ້ໂໝດແບ່ງໜ້າຈໍໂດຍໃຫ້ແອັບຢູ່ເບື້ອງຊ້າຍ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ສະຫຼັບໄປໃຊ້ໂໝດເຕັມຈໍ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຂວາ ຫຼື ທາງລຸ່ມໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ສະຫຼັບໄປໃຊ້ແອັບຢູ່ຊ້າຍ ຫຼື ທາງເທິງໃນຂະນະທີ່ໃຊ້ແບ່ງໜ້າຈໍ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ໃນລະຫວ່າງແບ່ງໜ້າຈໍ: ໃຫ້ປ່ຽນຈາກແອັບໜຶ່ງເປັນອີກແອັບໜຶ່ງ"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ເມນູເປີດປິດ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ໜ້າຈໍລັອກ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ທ່ານສາມາດຊອກຫາສະຖານທີ່ຂອງໂທລະສັບເຄື່ອງນີ້ໄດ້ດ້ວຍແອັບຊອກຫາອຸປະກອນຂອງຂ້ອຍເຖິງແມ່ນວ່າຈະປິດເຄື່ອງຢູ່ກໍຕາມ"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ກຳລັງປິດເຄື່ອງ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ເບິ່ງຂັ້ນຕອນການເບິ່ງແຍງ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ເບິ່ງຂັ້ນຕອນການເບິ່ງແຍງ"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ໄປຫາໜ້າຫຼັກ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ເບິ່ງແອັບຫຼ້າສຸດ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ແລ້ວໆ"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"ກະລຸນາລອງໃໝ່!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ກັບຄືນ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ປັດຊ້າຍ ຫຼື ຂວາໂດຍໃຊ້ມືສາມນິ້ວຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ດີ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ທ່ານໃຊ້ທ່າທາງກັບຄືນສຳເລັດແລ້ວ."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"ເພື່ອກັບຄືນໂດຍໃຊ້ແຜ່ນສໍາຜັດຂອງທ່ານ, ໃຫ້ປັດຊ້າຍ ຫຼື ຂວາໂດຍໃຊ້ສາມນິ້ວ"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ໄປຫາໜ້າຫຼັກ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ປັດຂຶ້ນໂດຍໃຊ້ມືສາມນິ້ວຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ດີຫຼາຍ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ທ່ານໃຊ້ທ່າທາງໄປໜ້າຫຼັກສຳເລັດແລ້ວ"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"ປັດຂຶ້ນດ້ວຍສາມນິ້ວເທິງແຜ່ນສຳຜັດຂອງທ່ານເພື່ອໄປຫາໂຮມສະກຣີນຂອງທ່ານ"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ເບິ່ງແອັບຫຼ້າສຸດ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ປັດຂຶ້ນໂດຍໃຊ້ມືສາມນິ້ວແລ້ວຄ້າງໄວ້ຢູ່ແຜ່ນສໍາຜັດຂອງທ່ານ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ດີຫຼາຍ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ທ່ານເບິ່ງທ່າທາງຂອງແອັບຫຼ້າສຸດສຳເລັດແລ້ວ."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"ເພື່ອເບິ່ງແອັບຫຼ້າສຸດ, ໃຫ້ປັດຂຶ້ນແລ້ວຄ້າງໄວ້ໂດຍໃຊ້ສາມນິ້ວເທິງແຜ່ນສຳຜັດຂອງທ່ານ"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ເບິ່ງແອັບທັງໝົດ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ດີຫຼາຍ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ທ່ານເບິ່ງທ່າທາງຂອງແອັບທັງໝົດສຳເລັດແລ້ວ"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"ກົດປຸ່ມຄຳສັ່ງຢູ່ແປ້ນພິມຂອງທ່ານເພື່ອເບິ່ງແອັບທັງໝົດຂອງທ່ານ"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ພາບເຄື່ອນໄຫວຂອງບົດສອນການນຳໃຊ້, ຄລິກເພື່ອຢຸດຊົ່ວຄາວ ແລະ ສືບຕໍ່ຫຼິ້ນ."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ໄຟປຸ່ມແປ້ນພິມ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"ລະດັບທີ %1$d ຈາກ %2$d"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 91e17a7..bfdd89f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Prisijungimas prie palydovo kritiniu atveju"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Skambučiai pagalbos numeriu arba pagalbos iškvietimas kritiniu atveju"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"„<xliff:g id="CARRIER_NAME">%1$s</xliff:g>“, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nėra signalo"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"viena juosta"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dvi juostos"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"trys juostos"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"keturios juostos"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"stiprus signalas"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Rodoma pokalbių pranešimų viršuje ir kaip profilio nuotrauka užrakinimo ekrane, burbule, pertraukia netrukdymo režimą"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritetiniai"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“ nepalaiko pokalbių funkcijų"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Pateikti atsiliepimą apie rinkinį"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Šių pranešimų keisti negalima."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Skambučių pranešimų keisti negalima."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Šios grupės pranešimai čia nekonfigūruojami"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Užrakinti ekraną"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Sukurti pastabą"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kelių užduočių atlikimas"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Naudokite išskaidyto ekrano režimą su programa dešinėje"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Naudokite išskaidyto ekrano režimą su programa kairėje"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Perjunkite į viso ekrano režimą"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Perjunkite į programą dešinėje arba apačioje išskaidyto ekrano režimu"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Perjunkite į programą kairėje arba viršuje išskaidyto ekrano režimu"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Išskaidyto ekrano režimu: pakeisti iš vienos programos į kitą"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Įjungimo meniu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Užrakinimo ekranas"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Šį telefoną galite rasti naudodami programą „Rasti įrenginį“, net jei jis išjungtas"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Išjungiama…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Žr. priežiūros veiksmus"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Žr. priežiūros veiksmus"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Eikite į pagrindinį puslapį"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Peržiūrėti naujausias programas"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Atlikta"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"Bandykite dar kartą!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Grįžti"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Braukite kairėn arba dešinėn trimis pirštais bet kur jutiklinėje dalyje"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Šaunu!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Atlikote grįžimo atgal gestą."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"Jei norite grįžti naudodami jutiklinę dalį, perbraukite kairėn arba dešinėn trimis pirštais"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Eikite į pagrindinį ekraną"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Braukite viršun trimis pirštais bet kur jutiklinėje dalyje"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Puiku!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Atlikote perėjimo į pagrindinį ekraną gestą"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"Perbraukite viršun trimis pirštais jutiklinėje dalyje, kad pereitumėte į pagrindinį ekraną"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Peržiūrėti naujausias programas"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Braukite viršun trimis pirštais bet kur jutiklinėje dalyje ir palaikykite"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Puiku!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Atlikote naujausių programų peržiūros gestą."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Peržiūrėkite naujausias programas, jutiklinėje dalyje perbraukę aukštyn trimis pirštais ir palaikę"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Žr. visas programas"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Paspauskite klaviatūros veiksmų klavišą"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Puikiai padirbėta!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Atlikote visų programų peržiūros gestą"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"Paspauskite klaviatūros veiksmų klavišą, kad peržiūrėtumėte visas programas"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Mokomoji animacija. Spustelėkite, kad pristabdytumėte ir tęstumėte atkūrimą."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatūros foninis apšvietimas"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d lygis iš %2$d"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index c06c2ba..9208c7e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Logrīki"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Lai pievienotu saīsni “Logrīki”, iestatījumos noteikti iespējojiet opciju “Rādīt logrīkus bloķēšanas ekrānā”."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Iestatījumi"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Poga “Rādīt ekrānsaudzētāju”"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelīta SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ārkārtas izsaukumi vai ārkārtas zvani"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nav signāla"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"viena josla"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"divas joslas"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"trīs joslas"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"četras joslas"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"pilna piekļuve signālam"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Parādās sarunu paziņojumu augšdaļā un kā profila attēls bloķēšanas ekrānā, arī kā burbulis, pārtrauc režīmu “Netraucēt”."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritārs"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> netiek atbalstītas sarunu funkcijas."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Sniegt atsauksmes par paziņojumu grupu"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Šos paziņojumus nevar modificēt."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Paziņojumus par zvaniem nevar modificēt."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Šeit nevar konfigurēt šo paziņojumu grupu."</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Bloķēt ekrānu"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Izveidot piezīmi"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Vairākuzdevumu režīms"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Izmantot ekrāna sadalīšanu ar lietotni labajā pusē"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Izmantot ekrāna sadalīšanu ar lietotni kreisajā pusē"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Pārslēgšana pilnekrāna režīmā"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Pāriet uz lietotni pa labi/lejā, kamēr izmantojat sadalīto ekrānu."</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Pāriet uz lietotni pa kreisi/augšā, kamēr izmantojat sadalīto ekrānu."</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ekrāna sadalīšanas režīmā: pārvietot lietotni no viena ekrāna uz otru"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Barošanas izvēlne"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Bloķēšanas ekrāns"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Lietotni “Atrast ierīci” var izmantot šī tālruņa atrašanās vietas noteikšanai arī tad, ja tālrunis ir izslēgts."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Notiek izslēgšana…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Skatīt apkopes norādījumus"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Skatīt apkopes norādījumus"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Pāriet uz sākuma ekrānu"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Skatīt nesen izmantotās lietotnes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gatavs"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Atpakaļ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Skārienpaliktnī ar trīs pirkstiem velciet pa kreisi vai pa labi."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Lieliski!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Jūs sekmīgi veicāt atgriešanās žestu."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pāreja uz sākuma ekrānu"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Skārienpaliktnī ar trīs pirkstiem velciet augšup."</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Lieliski!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Jūs sekmīgi veicāt sākuma ekrāna atvēršanas žestu."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Nesen izmantoto lietotņu skatīšana"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Skārienpaliktnī ar trīs pirkstiem velciet augšup un turiet."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Lieliski!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Jūs sekmīgi veicāt nesen izmantoto lietotņu skatīšanas žestu."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Skatīt visas lietotnes"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tastatūrā nospiediet darbību taustiņu."</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Lieliski!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Jūs sekmīgi veicāt visu lietotņu skatīšanas žestu."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Mācību animācija. Noklikšķiniet, lai pārtrauktu un atsāktu atskaņošanu."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Tastatūras fona apgaismojums"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Līmenis numur %1$d, kopā ir %2$d"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index a1e6017..15f2435 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виџети"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"За да ја додадете кратенката „Виџети“, погрижете се да биде овозможен „Прикажување виџети на заклучен екран“ во „Поставки“."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Поставки"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Копче за прикажување на штедачот на екран"</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Известувања"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Разговори"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Избриши ги сите бесчујни известувања"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Отвори ги поставките за известувања"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Известувањата се паузирани од „Не вознемирувај“"</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Нема известувања}=1{Известувањата ги паузираше {mode}}=2{Известувањата ги паузираа {mode} и уште еден режим}one{Известувањата ги паузираа {mode} и уште # режим}other{Известувањата ги паузираа {mode} и уште # режими}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Започни сега"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Сателитски SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Итни повици или SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"нема сигнал"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"една цртичка"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"две цртички"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"три цртички"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"четири цртички"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"полн сигнал"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Се прикажува најгоре во известувањата за разговор и како профилна слика на заклучен екран, се појавува како балонче, го прекинува „Не вознемирувај“"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддржува функции за разговор"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Испрати повратни информации за пакет"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Овие известувања не може да се изменат"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Известувањата за повици не може да се изменат."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Оваа група известувања не може да се конфигурира тука"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заклучете го екранот"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Фатете белешка"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Мултитаскинг"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Користете поделен екран со апликацијата оддесно"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Користете поделен екран со апликацијата одлево"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Префрлете се на цел екран"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Префрлете се на апликацијата десно или долу при користењето поделен екран"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Префрлете се на апликацијата лево или горе при користењето поделен екран"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"При поделен екран: префрлете ги аплик. од едната на другата страна"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени на копчето за вклучување"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Заклучен екран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Може да го лоцирате телефонов со „Најди го мојот уред“ дури и кога е исклучен"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Се исклучува…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Прикажи ги чекорите за грижа за уредот"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Прикажи ги чекорите за грижа за уредот"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Оди на почетниот екран"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прикажи ги неодамнешните апликации"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Повлечете налево или надесно со три прста на допирната подлога"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Одлично!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Го научивте движењето за враќање назад."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Одете на почетниот екран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Повлечете нагоре со три прсти на допирната подлога"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Одлично!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Го завршивте движењето за враќање на почетниот екран"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прикажи ги неодамнешните апликации"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Повлечете нагоре и задржете со три прста на допирната подлога"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Одлично!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Го завршивте движењето за прегледување на неодамнешните апликации."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Прегледајте ги сите апликации"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Притиснете го копчето за дејство на тастатурата"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Браво!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Го завршивте движењето за прегледување на сите апликации"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Анимација за упатство, кликнете за ја паузирате и да ја продолжите репродукцијата."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Осветлување на тастатура"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ниво %1$d од %2$d"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 4dc40f8..0f8417e 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -531,7 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"വിജറ്റുകൾ"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"വിജറ്റുകൾ\" കുറുക്കുവഴി ചേർക്കാൻ, ക്രമീകരണത്തിൽ \"ലോക്ക് സ്‌ക്രീനിൽ വിജറ്റുകൾ കാണിക്കുക\" പ്രവർത്തനക്ഷമമാക്കിയെന്ന് ഉറപ്പാക്കുക."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ക്രമീകരണം"</string>
-    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"സ്‌ക്രീൻ സേവർ ബട്ടൺ കാണിക്കുക"</string>
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"സ്‌ക്രീൻ സേവർ കാണിക്കുക ബട്ടൺ"</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>
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"സാറ്റലൈറ്റ് SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"എമർജൻസി കോൾ അല്ലെങ്കിൽ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"സിഗ്നൽ ഇല്ല"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ഒരു ബാർ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"രണ്ട് ബാറുകൾ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"മൂന്ന് ബാറുകൾ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"നാല് ബാറുകൾ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"മികച്ച സിഗ്‌നൽ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"സംഭാഷണ അറിയിപ്പുകളുടെ മുകളിലും സ്ക്രീൻ ലോക്കായിരിക്കുമ്പോൾ ഒരു പ്രൊഫൈൽ ചിത്രമായും ബബിൾ രൂപത്തിൽ ദൃശ്യമാകുന്നു, ശല്യപ്പെടുത്തരുത് മോഡ് തടസ്സപ്പെടുത്തുന്നു"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"മുൻഗണന"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"സംഭാഷണ ഫീച്ചറുകളെ <xliff:g id="APP_NAME">%1$s</xliff:g> പിന്തുണയ്‌ക്കുന്നില്ല"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ബണ്ടിൽ ഫീഡ്ബാക്ക് നൽകുക"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ഈ അറിയിപ്പുകൾ പരിഷ്ക്കരിക്കാനാവില്ല."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"കോൾ അറിയിപ്പുകൾ പരിഷ്‌കരിക്കാനാകുന്നില്ല."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"അറിയിപ്പുകളുടെ ഈ ഗ്രൂപ്പ് ഇവിടെ കോണ്‍ഫിഗര്‍ ചെയ്യാൻ കഴിയില്ല"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ലോക്ക് സ്‌ക്രീൻ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ഒരു കുറിപ്പെടുക്കുക"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"മൾട്ടിടാസ്‌കിംഗ്"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"വലതുവശത്തുള്ള ആപ്പിനൊപ്പം സ്‌ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ഇടതുവശത്തുള്ള ആപ്പിനൊപ്പം സ്‌ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുക"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"പൂർണ്ണ സ്‌ക്രീനിലേക്ക് മാറുക"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ വലതുവശത്തെ/താഴത്തെ ആപ്പിലേക്ക് മാറുക"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"സ്ക്രീൻ വിഭജന മോഡ് ഉപയോഗിക്കുമ്പോൾ ഇടതുവശത്തെ/മുകളിലെ ആപ്പിലേക്ക് മാറൂ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"സ്‌ക്രീൻ വിഭജന മോഡിൽ: ഒരു ആപ്പിൽ നിന്ന് മറ്റൊന്നിലേക്ക് മാറുക"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"പവർ മെനു"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"പേജ് <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ലോക്ക് സ്‌ക്രീൻ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ഓഫായിരിക്കുമ്പോഴും Find My Device ഉപയോഗിച്ച് നിങ്ങൾക്ക് ഈ ഫോൺ കണ്ടെത്താനാകും"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ഷട്ട്‌ഡൗൺ ചെയ്യുന്നു…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"പരിപാലന നിർദ്ദേശങ്ങൾ കാണുക"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"പരിപാലന നിർദ്ദേശങ്ങൾ കാണുക"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ഹോമിലേക്ക് പോകുക"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"പൂർത്തിയായി"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"മടങ്ങുക"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ടച്ച്‌പാഡിൽ മൂന്ന് വിരലുകൾ കൊണ്ട് ഇടത്തേക്കോ വലത്തേക്കോ സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"കൊള്ളാം!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"മടങ്ങുക ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ഹോമിലേക്ക് പോകൂ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ടച്ച്‌പാഡിൽ മൂന്ന് വിരലുകൾ ഉപയോഗിച്ച് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"കൊള്ളാം!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ഹോം ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"നിങ്ങളുടെ ടച്ച്പാഡിൽ മൂന്ന് വിരലുകൾ കൊണ്ട് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്‌ത് പിടിക്കുക"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"കൊള്ളാം!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"അടുത്തിടെയുള്ള ആപ്പുകൾ കാണുക എന്ന ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"എല്ലാ ആപ്പുകളും കാണുക"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"നിങ്ങളുടെ കീബോർഡിലെ ആക്ഷൻ കീ അമർത്തുക"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"അഭിനന്ദനങ്ങൾ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"\'എല്ലാ ആപ്പുകളും കാണുക\' ജെസ്ച്ചർ നിങ്ങൾ പൂർത്തിയാക്കി"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ട്യൂട്ടോറിയൽ ആനിമേഷൻ, താൽക്കാലികമായി നിർത്താനും പ്ലേ പുനരാരംഭിക്കാനും ക്ലിക്ക് ചെയ്യുക."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"കീബോഡ് ബാക്ക്‌ലൈറ്റ്"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-ൽ %1$d-ാമത്തെ ലെവൽ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 1343634..47a5468 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджет"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Виджет\"-ийн товчлол нэмэхийн тулд \"Түгжээтэй дэлгэц дээр виджет харуулах\"-ыг тохиргоонд идэвхжүүлсэн эсэхийг нягтална уу."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Тохиргоо"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Дэлгэц амраагчийг харуулах товч"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хиймэл дагуул SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Яаралтай дуудлага эсвэл SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"дохио байхгүй"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"нэг шон"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"хоёр шон"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"гурван шон"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"дөрвөн шон"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"дохио дүүрэн"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Харилцан ярианы мэдэгдлийн дээд талд болон түгжигдсэн дэлгэц дээр профайл зураг байдлаар харуулах бөгөөд бөмбөлөг хэлбэрээр харагдана. Бүү саад бол горимыг тасалдуулна"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Чухал"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь харилцан ярианы онцлогуудыг дэмждэггүй"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Багц санал хүсэлт өгөх"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Эдгээр мэдэгдлийг өөрчлөх боломжгүй."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Дуудлагын мэдэгдлийг өөрчлөх боломжгүй."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Энэ бүлэг мэдэгдлийг энд тохируулах боломжгүй байна"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Түгжээтэй дэлгэц"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Тэмдэглэл хөтлөх"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Олон ажил зэрэг хийх"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Аппыг баруун талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Аппыг зүүн талд байгаагаар дэлгэцийг хуваахыг ашиглах"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Бүтэн дэлгэц рүү сэлгэх"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Дэлгэц хуваахыг ашиглаж байхдаа баруун талд эсвэл доор байх апп руу сэлгэ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Дэлгэц хуваахыг ашиглаж байхдаа зүүн талд эсвэл дээр байх апп руу сэлгэ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Дэлгэц хуваах үеэр: аппыг нэгээс нөгөөгөөр солих"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Асаах/унтраах цэс"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Түгжээтэй дэлгэц"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Та энэ утсыг унтраалттай байсан ч Миний төхөөрөмжийг олохоор байршлыг нь тогтоох боломжтой"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Унтрааж байна…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Хянамж болгоомжийн алхмыг харах"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Хянамж болгоомжийн алхмыг харах"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Нүүр хуудас руу очих"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Саяхны аппуудыг харах"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Болсон"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Буцах"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Мэдрэгч самбар дээрээ гурван хуруугаа ашиглан зүүн эсвэл баруун тийш шударна уу"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Янзтай!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Та буцах зангааг гүйцэтгэлээ."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Үндсэн нүүр лүү очих"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Мэдрэгч самбар дээрээ гурван хуруугаараа дээш шударна уу"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Үнэхээр сайн ажиллалаа!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Та үндсэн нүүр лүү очих зангааг гүйцэтгэлээ"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Саяхны аппуудыг харах"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Мэдрэгч самбар дээрээ гурван хуруугаа ашиглан дээш шудраад, удаан дарна уу"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Сайн байна!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Та саяхны аппуудыг харах зангааг гүйцэтгэсэн."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Бүх аппыг харах"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Гар дээрх тусгай товчлуурыг дарна уу"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Сайн байна!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Та бүх аппыг харах зангааг гүйцэтгэлээ"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Зааврын анимаци, түр зогсоохын тулд товшиж, үргэлжлүүлэн тоглуулна уу."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Гарын арын гэрэл"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d-с %1$d-р түвшин"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 3f902d4..b5c298b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"विजेट"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"विजेट\" शॉर्टकट जोडण्यासाठी, सेटिंग्जमध्ये \"लॉक स्‍क्रीनवर विजेट दाखवा\" सुरू असल्याची खात्री करा."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"सेटिंग्ज"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"स्क्रीनसेव्हर दाखवा बटण"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"सॅटेलाइट SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आणीबाणी कॉल किंवा SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"कोणताही सिग्नल नाही"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"एक बार"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"दोन बार"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"तीन बार"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"चार बार"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"पूर्ण सिग्नल"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्‍याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्‍याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"संभाषण सूचनांच्या वरती आणि लॉक स्क्रीनवरील प्रोफाइल फोटो म्हणून दिसते, बबल म्हणून दिसते, व्यत्यय आणू नका यामध्ये अडथळा आणते"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राधान्य"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> हे संभाषण वैशिष्ट्यांना सपोर्ट करत नाही"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"बंडलसंबंधित फीडबॅक द्या"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"या सूचनांमध्ये सुधारणा केली जाऊ शकत नाही."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कॉलशी संबंधित सूचनांमध्ये फेरबदल केला जाऊ शकत नाही."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"या सूचनांचा संच येथे कॉन्फिगर केला जाऊ शकत नाही"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"लॉक स्क्रीन"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"नोंद घ्या"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"मल्टिटास्किंग"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ॲप उजवीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ॲप डावीकडे ठेवून स्प्लिट स्क्रीन वापरा"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"फुल स्क्रीनवर स्विच करणे"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रीन वापरताना उजवीकडील किंवा खालील अ‍ॅपवर स्विच करा"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रीन वापरताना डावीकडील किंवा वरील अ‍ॅपवर स्विच करा"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"स्प्लिट स्क्रीनदरम्यान: एक अ‍ॅप दुसऱ्या अ‍ॅपने बदला"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पॉवर मेनू"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g> पेज"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्‍क्रीन"</string>
-    <string name="finder_active" msgid="7907846989716941952">"तुम्ही हा फोन बंद असतानादेखील Find My Device वापरून तो शोधू शकता"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"बंद होत आहे…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"काय काळजी घ्यावी ते पहा"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"काय काळजी घ्यावी ते पहा"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"होमवर जा"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"अलीकडील अ‍ॅप्स पहा"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"पूर्ण झाले"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"मागे जा"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"तुमच्या टचपॅडवर तीन बोटांनी डावीकडे किंवा उजवीकडे स्‍वाइप करा"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"छान!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"तुम्ही गो बॅक जेश्चर पूर्ण केले."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमवर जा"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"तुमच्या टचपॅडवर तीन बोटांनी वर स्वाइप करा"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"उत्तम कामगिरी!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"तुम्ही गो होम जेश्चर पूर्ण केले आहे"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"अलीकडील अ‍ॅप्स पहा"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"तुमच्या टचपॅडवर तीन बोटांनी वर स्वाइप करून धरून ठेवा"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"उत्तम कामगिरी!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तुम्ही अलीकडील ॲप्स पाहण्याचे जेश्चर पूर्ण केले आहे."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"सर्व अ‍ॅप्स पहा"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"तुमच्या कीबोर्डवर अ‍ॅक्शन की प्रेस करा"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"खूप छान!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"तुम्ही ॲप्स पाहण्याचे जेश्चर पूर्ण केले आहे"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ट्यूटोरियल अ‍ॅनिमेशन थांबवण्यासाठी किंवा पुन्हा सुरू करण्यासाठी प्ले करा वर क्लिक करा."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"कीबोर्ड बॅकलाइट"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d पैकी %1$d पातळी"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 0900288..481f662 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan kecemasan atau SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"tiada isyarat"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"satu bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dua bar"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tiga bar"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"empat bar"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"isyarat penuh"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ditunjukkan di bahagian atas pemberitahuan perbualan dan sebagai gambar profil pada skrin kunci, muncul sebagai gelembung, mengganggu Jangan Ganggu"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Keutamaan"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak menyokong ciri perbualan"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Berikan Maklum Balas Himpunan"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Pemberitahuan ini tidak boleh diubah suai."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Pemberitahuan panggilan tidak boleh diubah suai."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Kumpulan pemberitahuan ini tidak boleh dikonfigurasikan di sini"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kunci skrin"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Catat nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Berbilang tugas"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Gunakan skrin pisah dengan apl pada sebelah kanan"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Gunakan skrin pisah dengan apl pada sebelah kiri"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Beralih kepada skrin penuh"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Tukar kepada apl di sebelah kanan/bawah semasa menggunakan skrin pisah"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Tukar kepada apl di sebelah kiri/atas semasa menggunakan skrin pisah"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Semasa skrin pisah: gantikan apl daripada satu apl kepada apl lain"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu kuasa"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> daripada <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Kunci skrin"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Anda boleh mengesan telefon ini dengan Find My Device walaupun apabila telefon ini dimatikan kuasa"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Mematikan…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Lihat langkah penjagaan"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Lihat langkah penjagaan"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Akses laman utama"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Lihat apl terbaharu"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Selesai"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kembali"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Leret ke kiri atau ke kanan menggunakan tiga jari pada pad sentuh"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bagus!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Anda telah melengkapkan gerak isyarat kembali."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Akses laman utama"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Leret ke atas dengan tiga jari pada pad sentuh anda"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bagus!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Anda telah melengkapkan gerak isyarat akses laman utama"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Lihat apl terbaharu"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Leret ke atas dan tahan menggunakan tiga jari pada pad sentuh"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Syabas!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Anda telah melengkapkan gerak isyarat lihat apl terbaharu."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Lihat semua apl"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tekan kekunci tindakan pada papan kekunci anda"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Syabas!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Anda telah melengkapkan gerak isyarat lihat semua apl"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animasi tutorial, klik untuk menjeda dan menyambung semula main."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Cahaya latar papan kekunci"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Tahap %1$d daripada %2$d"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 186b60f..bde5f57 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"အရေးပေါ်ဖုန်းခေါ်ခြင်း (သို့) SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>၊ <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>။"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"လိုင်းမရှိပါ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"တစ်ဘား"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"နှစ်ဘား"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"သုံးဘား"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"လေးဘား"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"လိုင်းအပြည့်ရှိသည်"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"စကားဝိုင်း အကြောင်းကြားချက်များ၏ ထိပ်ပိုင်းနှင့် ပရိုဖိုင်ပုံအဖြစ် လော့ခ်မျက်နှာပြင်တွင် ပြသည်။ ပူဖောင်းကွက်အဖြစ် မြင်ရပြီး ‘မနှောင့်ယှက်ရ’ ကို ကြားဖြတ်သည်"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ဦးစားပေး"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> က စကားဝိုင်းဝန်ဆောင်မှုများကို မပံ့ပိုးပါ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"အတွဲလိုက် အကြံပြုချက်ပေးရန်"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ဤအကြောင်းကြားချက်များကို ပြုပြင်၍ မရပါ။"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ခေါ်ဆိုမှုအကြောင်းကြားချက်များကို ပြင်၍မရပါ။"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ဤအကြောင်းကြားချက်အုပ်စုကို ဤနေရာတွင် စီစဉ်သတ်မှတ်၍ မရပါ"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"လော့ခ်မျက်နှာပြင်"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"မှတ်စုရေးရန်"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"တစ်ပြိုင်နက် များစွာလုပ်ခြင်း"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"အက်ပ်ကို ညာ၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"အက်ပ်ကို ဘယ်၌ထားကာ မျက်နှာပြင် ခွဲ၍ပြသခြင်း သုံးရန်"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ဖန်သားပြင်အပြည့် ပြောင်းခြင်း"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"မျက်နှာပြင်ခွဲ၍ပြသခြင်း သုံးစဉ် ညာ (သို့) အောက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးစဉ် ဘယ် (သို့) အထက်ရှိအက်ပ်သို့ ပြောင်းရန်"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"မျက်နှာပြင် ခွဲ၍ပြသစဉ်- အက်ပ်တစ်ခုကို နောက်တစ်ခုနှင့် အစားထိုးရန်"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ပါဝါမီနူး"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်မျက်နှာပြင်"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ပါဝါပိတ်ထားသော်လည်း Find My Device ဖြင့် ဤဖုန်းကို ရှာနိုင်သည်"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"စက်ပိတ်နေသည်…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ပင်မစာမျက်နှာသို့ သွားရန်"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"မကြာသေးမီကအက်ပ်များကို ကြည့်ရန်"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ပြီးပြီ"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ပြန်သွားရန်"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"သင့်တာ့ချ်ပက်တွင် လက်သုံးချောင်းဖြင့် ဘယ် (သို့) ညာသို့ ပွတ်ဆွဲပါ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ကောင်းပါသည်။"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"နောက်သို့လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ပင်မစာမျက်နှာသို့ သွားရန်"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"တာ့ချ်ပက်ပေါ်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"တော်ပါပေသည်။"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ပင်မစာမျက်နှာသို့သွားသည့် လက်ဟန် အပြီးသတ်လိုက်ပါပြီ"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"မကြာသေးမီကအက်ပ်များကို ကြည့်ခြင်း"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"သင့်တာ့ချ်ပက်တွင် လက်သုံးချောင်းဖြင့် အပေါ်သို့ပွတ်ဆွဲပြီး ဖိထားပါ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"တော်ပါပေသည်။"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"မကြာသေးမီကအက်ပ်များကို ကြည့်ခြင်းလက်ဟန် သင်ခန်းစာပြီးပါပြီ။"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"အက်ပ်အားလုံးကို ကြည့်ခြင်း"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ကီးဘုတ်တွင် လုပ်ဆောင်ချက်ကီး နှိပ်ပါ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"အလွန်ကောင်းပါသည်။"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"အက်ပ်အားလုံးကို ကြည့်ခြင်းလက်ဟန် သင်ခန်းစာပြီးပါပြီ"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ရှင်းလင်းပို့ချချက် လှုပ်ရှားသက်ဝင်ပုံ၊ ခဏရပ်ပြီး ဆက်ဖွင့်ရန် နှိပ်ပါ။"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ကီးဘုတ်နောက်မီး"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"အဆင့် %2$d အနက် %1$d"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1ef544b..9dd0f99 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Moduler"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"For å legge til «Moduler»-snarveien, sørg for at «Vis moduler på låseskjermen» er slått på i innstillingene."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Innstillinger"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Knapp for å vise skjermspareren"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-alarm via satellitt"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødanrop eller SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ikke noe signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"én strek"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"to streker"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tre streker"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"fire streker"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"full signalstyrke"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Vises øverst på samtalevarsler og som et profilbilde på låseskjermen, vises som en boble, avbryter «Ikke forstyrr»"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> støtter ikke samtalefunksjoner"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Gi tilbakemelding om pakken"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Disse varslene kan ikke endres."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Anropsvarsler kan ikke endres."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Denne varselgruppen kan ikke konfigureres her"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Låseskjerm"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ta et notat"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Bruk delt skjerm med appen til høyre"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Bruk delt skjerm med appen til venstre"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Bytt til fullskjerm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bytt til appen til høyre eller under mens du bruker delt skjerm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bytt til appen til venstre eller over mens du bruker delt skjerm"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"I delt skjerm: Bytt ut en app"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Av/på-meny"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskjerm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Du kan finne denne telefonen med Finn enheten min, selv når den er slått av"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Slår av …"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Se hva du kan gjøre"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se hva du kan gjøre"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Gå til startsiden"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se nylige apper"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Ferdig"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Gå tilbake"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Sveip til venstre eller høyre med tre fingre på styreflaten"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bra!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du har fullført bevegelsen for å gå tilbake."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Gå til startsiden"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Sveip opp med tre fingre på styreflaten"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bra jobbet!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Du har fullført bevegelsen for å gå til startskjermen"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se nylige apper"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Sveip opp og hold med tre fingre på styreflaten"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bra jobbet!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du har fullført bevegelsen for å se nylige apper."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Se alle apper"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Trykk på handlingstasten på tastaturet"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bra!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Du har fullført bevegelsen for å se alle apper"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Veiledningsanimasjon. Klikk for å sette avspillingen på pause og gjenoppta den."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrunnslys for tastatur"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 9a97010..968fd51 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"स्याटलाइट SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपत्कालीन कल वा SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>।"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"सिग्नल छैन"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"एउटा बार"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"दुई वटा बार"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"तीन वटा बार"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"चार वटा बार"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"पूरै सिग्नल छ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस  कस्टम गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"यो वार्तालापका सूचनाहरूको सिरानमा, बबलका रूपमा र लक स्क्रिनमा प्रोफाइल फोटोका रूपमा देखिन्छ। साथै, यसले गर्दा \'बाधा नपुऱ्याउनुहोस्\' नामक सुविधामा अवरोध आउँछ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा वार्तालापसम्बन्धी सुविधा प्रयोग गर्न मिल्दैन"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"बन्डलका बारेमा प्रतिक्रिया दिनुहोस्"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"यी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"कलसम्बन्धी सूचनाहरू परिमार्जन गर्न मिल्दैन।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"यहाँबाट सूचनाहरूको यो समूह कन्फिगर गर्न सकिँदैन"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"स्क्रिन लक गर्नुहोस्"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"नोट लेख्नुहोस्"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"एकै पटक एकभन्दा बढी एप चलाउन मिल्ने सुविधा"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"हालको एप दायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"हालको एप बायाँ भागमा पारेर स्प्लिट स्क्रिन प्रयोग गर्नुहोस्"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"फुल स्क्रिन प्रयोग गर्नुहोस्"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा दायाँ वा तलको एप चलाउनुहोस्"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"स्प्लिट स्क्रिन प्रयोग गर्दै गर्दा बायाँ वा माथिको एप चलाउनुहोस्"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"स्प्लिट स्क्रिन प्रयोग गरिएका बेला: एउटा स्क्रिनमा भएको एप अर्कोमा लैजानुहोस्"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेनु"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"लक स्क्रिन"</string>
-    <string name="finder_active" msgid="7907846989716941952">"तपाईं Find My Device प्रयोग गरी यो फोन अफ भए पनि यसको लोकेसन पत्ता लगाउन सक्नुहुन्छ"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"सट डाउन गरिँदै छ..."</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"डिभाइसको हेरचाह गर्ने तरिका हेर्नुहोस्"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिभाइसको हेरचाह गर्ने तरिका हेर्नुहोस्"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"होम स्क्रिनमा जानुहोस्"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"हालसालै चलाइएका एपहरू हेर्नुहोस्"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"सम्पन्न भयो"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"पछाडि जानुहोस्"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"तीन वटा औँला प्रयोग गरी टचप्याडमा बायाँ वा दायाँतिर स्वाइप गर्नुहोस्"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"राम्रो!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"तपाईंले जेस्चर प्रयोग गरी पछाडि जाने तरिका सिक्नुभएको छ।"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"होमपेजमा जानुहोस्"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"टचप्याडमा तीन वटा औँलाले माथितिर स्वाइप गर्नुहोस्"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"अद्भुत!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"तपाईंले \"होम स्क्रिनमा जानुहोस्\" नामक जेस्चर प्रयोग गर्ने तरिका सिक्नुभयो"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"हालसालै चलाइएका एपहरू हेर्नुहोस्"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"तीन वटा औँला प्रयोग गरी टचप्याडमा माथितिर स्वाइप गर्नुहोस् र होल्ड गर्नुहोस्"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"अद्भुत!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"तपाईंले जेस्चर प्रयोग गरी हालसालै चलाइएका एपहरू हेर्ने तरिका सिक्नुभएको छ।"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"सबै एपहरू हेर्नुहोस्"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"आफ्नो किबोर्डमा भएको एक्सन की थिच्नुहोस्"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"स्याबास!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"तपाईंले जेस्चर प्रयोग गरी सबै एपहरू हेर्ने तरिका सिक्नुभएको छ"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ट्युटोरियलको एनिमेसन, पज वा सुचारु गर्न क्लिक गर्नुहोस्।"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"किबोर्ड ब्याकलाइट"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d मध्ये %1$d औँ स्तर"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index c1eff5f..a77f5e4 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -108,6 +108,9 @@
 
     <color name="people_tile_background">@color/material_dynamic_secondary20</color>
 
+    <!-- Dark Theme colors for notification shade/scrim -->
+    <color name="shade_panel">@android:color/system_accent1_900</color>
+
     <!-- Keyboard shortcut helper dialog -->
     <color name="ksh_key_item_color">@*android:color/system_on_surface_variant_dark</color>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index e7fe5366..adc157b 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satelliet"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepen of SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"geen signaal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 streepje"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 streepjes"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 streepjes"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 streepjes"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signaal op volledige sterkte"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wordt getoond bovenaan gespreksmeldingen en als profielfoto op het vergrendelscherm, verschijnt als bubbel, onderbreekt Niet storen"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksfuncties"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Feedback over bundel geven"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Deze meldingen kunnen niet worden aangepast."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Gespreksmeldingen kunnen niet worden aangepast."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Deze groep meldingen kan hier niet worden ingesteld"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Scherm vergrendelen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Notitie maken"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasken"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Gesplitst scherm gebruiken met de app aan de rechterkant"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Gesplitst scherm gebruiken met de app aan de linkerkant"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Overschakelen naar volledig scherm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Naar de app rechts of onderaan gaan als je een gesplitst scherm gebruikt"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Naar de app links of bovenaan gaan als je een gesplitst scherm gebruikt"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Tijdens gesplitst scherm: een app vervangen door een andere"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aan/uit-menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Vergrendelscherm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Je kunt deze telefoon vinden met Vind mijn apparaat, ook als die uitstaat"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Uitzetten…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Onderhoudsstappen bekijken"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Onderhoudsstappen bekijken"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Naar startscherm"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Recente apps bekijken"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klaar"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Terug"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swipe met 3 vingers naar links of rechts op de touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Goed zo!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Je weet nu hoe je het gebaar voor terug maakt."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Naar startscherm"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swipe met 3 vingers omhoog op de touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Goed gedaan!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Je weet nu hoe je het gebaar Naar startscherm maakt"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Recente apps bekijken"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swipe met 3 vingers omhoog en houd vast op de touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Goed gedaan!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Je weet nu hoe je het gebaar Recente apps bekijken maakt."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Alle apps bekijken"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Druk op de actietoets op het toetsenbord"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Goed gedaan!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Je weet nu hoe je het gebaar Alle apps bekijken maakt"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial-animatie, klik om het afspelen te onderbreken en te hervatten."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Achtergrondverlichting van toetsenbord"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveau %1$d van %2$d"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 35704ea..12a13ff 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ସେଟେଲାଇଟ SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ଜରୁରୀକାଳୀନ କଲ କିମ୍ବା SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>।"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"କୌଣସି ସିଗନାଲ ନାହିଁ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ଗୋଟିଏ ବାର"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ଦୁଇଟି ବାର"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"ତିନୋଟି ବାର"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ଚାରୋଟି ବାର"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ସିଗନାଲ ପୂର୍ଣ୍ଣ ଅଛି"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍‍ ଇଣ୍ଟରଫେସ୍‍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍‍ UI ଟ୍ୟୁନର୍‍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍‌ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ବାର୍ତ୍ତାଳାପ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଶୀର୍ଷରେ ଏବଂ ଲକ୍ ସ୍କ୍ରିନରେ ଏକ ପ୍ରୋଫାଇଲ୍ ଛବି ଭାବେ ଦେଖାଏ, ଏକ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, \'ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\'କୁ ବାଧା ଦିଏ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବାର୍ତ୍ତାଳାପ ଫିଚରଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ ନାହିଁ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ବଣ୍ଡଲ ମତାମତ ପ୍ରଦାନ କରନ୍ତୁ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପରିବର୍ତ୍ତନ କରିହେବ ନାହିଁ।"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"କଲ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପରିବର୍ତ୍ତନ କରାଯାଇପାରିବ ନାହିଁ।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ଏଠାରେ ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକର ଗ୍ରୁପ୍ କନଫ୍ୟୁଗର୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ଲକ ସ୍କ୍ରିନ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ଏକ ନୋଟ ଲେଖନ୍ତୁ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ମଲ୍ଟିଟାସ୍କିଂ"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ଡାହାଣରେ ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ବାମରେ ଆପ ସହିତ ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନକୁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନକୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ଡାହାଣପଟର ବା ତଳର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ବ୍ୟବହାର କରିବା ସମୟରେ ବାମପଟର ବା ଉପରର ଆପକୁ ସୁଇଚ କରନ୍ତୁ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ସମୟରେ: କୌଣସି ଆପକୁ ଗୋଟିଏରୁ ଅନ୍ୟ ଏକ ଆପରେ ବଦଳାନ୍ତୁ"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ପାୱାର ମେନୁ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ପୃଷ୍ଠା <xliff:g id="ID_1">%1$d</xliff:g> ମୋଟ <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"ଲକ ସ୍କ୍ରିନ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ପାୱାର ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପଣ Find My Device ମାଧ୍ୟମରେ ଏହି ଫୋନକୁ ଖୋଜିପାରିବେ"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ବନ୍ଦ କରାଯାଉଛି…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ଯତ୍ନ ନେବା ପାଇଁ ଷ୍ଟେପଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ଯତ୍ନ ନେବା ପାଇଁ ଷ୍ଟେପଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ହୋମକୁ ଯାଆନ୍ତୁ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ବର୍ତ୍ତମାନର ଆପ୍ସ ଭ୍ୟୁ କରନ୍ତୁ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ହୋଇଗଲା"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ପଛକୁ ଫେରନ୍ତୁ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ଆପଣଙ୍କ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠି ବ୍ୟବହାର କରି ବାମ କିମ୍ବା ଡାହାଣକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ବଢ଼ିଆ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ଆପଣ \'ପଛକୁ ଫେରନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ହୋମକୁ ଯାଆନ୍ତୁ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ଆପଣଙ୍କ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିରେ ଉପରକୁ ସ୍ୱାଇପ କରନ୍ତୁ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ବଢ଼ିଆ କାମ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ଆପଣ \'ହୋମକୁ ଯାଆନ୍ତୁ\' ଜେଶ୍ଚର ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ବର୍ତ୍ତମାନର ଆପ୍ସକୁ ଭ୍ୟୁ କରନ୍ତୁ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ଆପଣଙ୍କ ଟଚପେଡରେ ତିନୋଟି ଆଙ୍ଗୁଠିକୁ ବ୍ୟବହାର କରି ଉପରକୁ ସ୍ୱାଇପ କରି ଧରି ରଖନ୍ତୁ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ବଢ଼ିଆ କାମ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ଆପଣ ବର୍ତ୍ତମାନର ଆପ୍ସ ଜେଶ୍ଚରକୁ ଭ୍ୟୁ କରିବା ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି।"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ସବୁ ଆପ ଭ୍ୟୁ କରନ୍ତୁ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ଆପଣଙ୍କର କୀବୋର୍ଡରେ ଆକ୍ସନ କୀ\'କୁ ଦବାନ୍ତୁ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ବହୁତ ବଢ଼ିଆ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ଆପଣ ସମସ୍ତ ଆପ୍ସ ଜେଶ୍ଚରକୁ ଭ୍ୟୁ କରିବା ସମ୍ପୂର୍ଣ୍ଣ କରିଛନ୍ତି"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ଟ୍ୟୁଟୋରିଆଲ ଆନିମେସନ, ପ୍ଲେ କରିବା ବିରତ କରି ପୁଣି ଆରମ୍ଭ କରିବାକୁ କ୍ଲିକ କରନ୍ତୁ।"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"କୀବୋର୍ଡ ବେକଲାଇଟ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dରୁ %1$d ନମ୍ବର ଲେଭେଲ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 68cd2b4..feaae0e 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"ਵਿਜੇਟ"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"ਵਿਜੇਟ\" ਸ਼ਾਰਟਕੱਟ ਨੂੰ ਸ਼ਾਮਲ ਕਰਨ ਲਈ, ਪੱਕਾ ਕਰੋ ਕਿ ਸੈਟਿੰਗਾਂ ਵਿੱਚ \"ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਦਿਖਾਓ\" ਚਾਲੂ ਹੈ।"</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"ਸੈਟਿੰਗਾਂ"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"\'ਸਕ੍ਰੀਨ-ਸੇਵਰ ਦਿਖਾਓ\' ਬਟਨ"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ਸੈਟੇਲਾਈਟ SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ ਜਾਂ ਸਹਾਇਤਾ"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ਕੋਈ ਸਿਗਨਲ ਨਹੀਂ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ਇੱਕ ਸਿਗਨਲ ਪੱਟੀ"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ਦੋ ਸਿਗਨਲ ਪੱਟੀਆਂ"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"ਤਿੰਨ ਸਿਗਨਲ ਪੱਟੀਆਂ"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"ਚਾਰ ਸਿਗਨਲ ਪੱਟੀਆਂ"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"ਪੂਰਾ ਸਿਗਨਲ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"ਗੱਲਬਾਤ ਸੂਚਨਾਵਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਅਤੇ ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਵਜੋਂ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਜੋ ਕਿ ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ ਅਤੇ \'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਸੁਵਿਧਾ ਵਿੱਚ ਵਿਘਨ ਵੀ ਪਾ ਸਕਦੀਆਂ ਹਨ"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ਤਰਜੀਹ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਐਪ ਗੱਲਬਾਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"ਬੰਡਲ ਬਾਰੇ ਵਿਚਾਰ ਮੁਹੱਈਆ ਕਰਵਾਓ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ਕਾਲ ਸੰਬੰਧੀ ਸੂਚਨਾਵਾਂ ਨੂੰ ਸੋਧਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ।"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ਇਹ ਸੂਚਨਾਵਾਂ ਦਾ ਗਰੁੱਪ ਇੱਥੇ ਸੰਰੂਪਿਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ਲਾਕ ਸਕ੍ਰੀਨ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"ਨੋਟ ਲਿਖੋ"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ਮਲਟੀਟਾਸਕਿੰਗ"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ਸੱਜੇ ਪਾਸੇ ਵਾਲੀ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ਖੱਬੇ ਪਾਸੇ ਵਾਲੀ ਐਪ ਨਾਲ ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ਪੂਰੀ-ਸਕ੍ਰੀਨ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਸੱਜੇ ਜਾਂ ਹੇਠਾਂ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਖੱਬੇ ਜਾਂ ਉੱਪਰ ਮੌਜੂਦ ਐਪ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੌਰਾਨ: ਇੱਕ ਐਪ ਨਾਲ ਦੂਜੀ ਐਪ ਨੂੰ ਬਦਲੋ"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ਪਾਵਰ ਮੀਨੂ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">" ਲਾਕ  ਸਕ੍ਰੀਨ"</string>
-    <string name="finder_active" msgid="7907846989716941952">"ਬੰਦ ਹੋਣ \'ਤੇ ਵੀ, ਤੁਸੀਂ ਇਸ ਫ਼ੋਨ ਨੂੰ Find My Device ਦੀ ਮਦਦ ਨਾਲ ਲੱਭ ਸਕਦੇ ਹੋ"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ਬੰਦ ਹੋ ਰਿਹਾ ਹੈ…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ਹੋਮ \'ਤੇ ਜਾਓ"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ਹੋ ਗਿਆ"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ਵਾਪਸ ਜਾਓ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਖੱਬੇ ਜਾਂ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ਵਧੀਆ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ਤੁਸੀਂ \'ਵਾਪਸ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ।"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ਹੋਮ \'ਤੇ ਜਾਓ"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਨਾਲ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"ਬਹੁਤ ਵਧੀਆ!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ਤੁਸੀਂ \'ਹੋਮ \'ਤੇ ਜਾਓ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ਆਪਣੇ ਟੱਚਪੈਡ \'ਤੇ ਤਿੰਨ ਉਂਗਲਾਂ ਦੀ ਵਰਤੋਂ ਕਰ ਕੇ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"ਬਹੁਤ ਵਧੀਆ!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ਤੁਸੀਂ \'ਹਾਲੀਆ ਐਪਾਂ ਦੇਖੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ ਹੈ।"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ਸਾਰੀਆਂ ਐਪਾਂ ਦੇਖੋ"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ਆਪਣੇ ਕੀ-ਬੋਰਡ \'ਤੇ ਕਾਰਵਾਈ ਕੁੰਜੀ ਨੂੰ ਦਬਾਓ"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ਬਹੁਤ ਵਧੀਆ!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ਤੁਸੀਂ \'ਸਾਰੀਆਂ ਐਪਾਂ ਦੇਖੋ\' ਦਾ ਇਸ਼ਾਰਾ ਪੂਰਾ ਕੀਤਾ ਹੈ"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ਟਿਊਟੋਰੀਅਲ ਐਨੀਮੇਸ਼ਨ, ਰੋਕਣ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰਨ ਲਈ ਕਲਿੱਕ ਕਰੋ।"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ਕੀ-ਬੋਰਡ ਬੈਕਲਾਈਟ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$d ਵਿੱਚੋਂ %1$d ਪੱਧਰ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a970e28..bd7496d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelitarne połączenie alarmowe"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Połączenia alarmowe lub SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"brak sygnału"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 pasek"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 paski"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 paski"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 paski"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"pełna moc sygnału"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Wyświetla się u góry powiadomień w rozmowach oraz jako zdjęcie profilowe na ekranie blokady, jako dymek, przerywa działanie trybu Nie przeszkadzać"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priorytetowe"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje funkcji rozmów"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Prześlij opinię o pakiecie"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tych powiadomień nie można zmodyfikować."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Powiadomień o połączeniach nie można modyfikować."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Tej grupy powiadomień nie można tu skonfigurować"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zablokuj ekran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Zanotuj"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Wielozadaniowość"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Podziel ekran z aplikacją widoczną po prawej"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Podziel ekran z aplikacją widoczną po lewej"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Włącz pełny ekran"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Przełącz się na aplikację po prawej lub poniżej na podzielonym ekranie"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Przełącz się na aplikację po lewej lub powyżej na podzielonym ekranie"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Podczas podzielonego ekranu: zastępowanie aplikacji"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu zasilania"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran blokady"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Możesz zlokalizować ten telefon w usłudze Znajdź moje urządzenie, nawet jeśli będzie wyłączony"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Wyłączam…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobacz instrukcję postępowania"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobacz instrukcję postępowania"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Otwórz stronę główną"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Wyświetlanie ostatnich aplikacji"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gotowe"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Wróć"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Przesuń 3 palcami w prawo lub w lewo na touchpadzie"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Super!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Gest przejścia wstecz został opanowany."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Otwórz stronę główną"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Przesuń 3 palcami w górę na touchpadzie"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Dobra robota!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Gest przechodzenia na ekran główny został opanowany"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Wyświetlanie ostatnich aplikacji"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Przesuń w górę za pomocą 3 palców na touchpadzie i przytrzymaj"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Brawo!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Znasz już gest wyświetlania ostatnio używanych aplikacji."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Wyświetl wszystkie aplikacje"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Naciśnij klawisz działania na klawiaturze"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Brawo!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Znasz już gest wyświetlania wszystkich aplikacji"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacja z samouczkiem. Kliknij, aby wstrzymać lub wznowić odtwarzanie."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podświetlenie klawiatury"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Poziom %1$d z %2$d"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index f28de4e..b2db120 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para adicionar o atalho Widgets, verifique se a opção \"Mostrar widgets na tela de bloqueio\" está ativada nas configurações."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configurações"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botão \"Mostrar protetor de tela\""</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"sem sinal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"uma barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"duas barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"três barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"quatro barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinal máximo"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparecem na parte superior das notificações de conversa, como uma foto do perfil na tela de bloqueio e como um balão. Interrompem o Não perturbe."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Enviar feedback sobre o pacote"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Usar a tela dividida com o app à direita"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Usar a tela dividida com o app à esquerda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Mudar para tela cheia"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mudar para o app à direita ou abaixo ao usar a tela dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mudar para o app à esquerda ou acima ao usar a tela dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Com a tela dividida: substituir um app por outro"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Desligando…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver etapas de cuidado"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ir para a página inicial"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver os apps recentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Deslize para a esquerda ou direita com 3 dedos no touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Legal!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Você concluiu o gesto para voltar."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Deslize para cima com 3 dedos no touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Muito bem!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Você concluiu o gesto para acessar a tela inicial"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver os apps recentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Deslize para cima com 3 dedos e mantenha"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todos os apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pressione a tecla de ação no teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Muito bem!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Você concluiu o gesto para ver todos os apps"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animação do tutorial. Clique para pausar ou retomar a reprodução."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 83aa9cf3..dcc8f02 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satélite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"sem sinal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinal completo"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparece na parte superior das notificações de conversas e como uma imagem do perfil no ecrã de bloqueio, surge como um balão, interrompe o modo Não incomodar"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> não suporta funcionalidades de conversa."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Enviar feedback sobre o pacote"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar estas notificações."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamadas."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar este grupo de notificações aqui."</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecrã de bloqueio"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Tire notas"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Execução de várias tarefas em simultâneo"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Use o ecrã dividido com a app à direita"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Use o ecrã dividido com a app à esquerda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Mude para ecrã inteiro"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mudar para a app à direita ou abaixo enquanto usa o ecrã dividido"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mude para a app à esquerda ou acima enquanto usa o ecrã dividido"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Durante o ecrã dividido: substituir uma app por outra"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu ligar/desligar"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ecrã de bloqueio"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Pode localizar este telemóvel com o serviço Localizar o meu dispositivo mesmo quando está desligado"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"A encerrar…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Veja os passos de manutenção"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Veja os passos de manutenção"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Aceder ao ecrã principal"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver apps recentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluir"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"Tente novamente!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Deslize rapidamente para a esquerda ou direita com 3 dedos no touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Boa!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Concluiu o gesto para retroceder."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"Para retroceder com o touchpad, deslize rapidamente para a esquerda ou direita com 3 dedos"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Aceder ao ecrã principal"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Deslize para cima com 3 dedos no touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"É assim mesmo!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Concluiu o gesto para aceder ao ecrã principal"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"Deslize rapidamente para cima com 3 dedos no touchpad para aceder ao ecrã principal"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver apps recentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Deslize rapidamente para cima sem soltar com 3 dedos no touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Concluiu o gesto para ver as apps recentes."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para ver as apps recentes, deslize rapidamente para cima sem soltar com 3 dedos no touchpad"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todas as apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Prima a tecla de ação no teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Muito bem!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Concluiu o gesto para ver todas as apps"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"Prima a tecla de ação no teclado para ver todas as suas apps"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animação do tutorial, clique para pausar e retomar a reprodução."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index f28de4e..b2db120 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgets"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Para adicionar o atalho Widgets, verifique se a opção \"Mostrar widgets na tela de bloqueio\" está ativada nas configurações."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Configurações"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Botão \"Mostrar protetor de tela\""</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"sem sinal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"uma barra"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"duas barras"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"três barras"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"quatro barras"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinal máximo"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Aparecem na parte superior das notificações de conversa, como uma foto do perfil na tela de bloqueio e como um balão. Interrompem o Não perturbe."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Enviar feedback sobre o pacote"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Não é possível modificar essas notificações."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Não é possível modificar as notificações de chamada."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Não é possível configurar esse grupo de notificações aqui"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Tela de bloqueio"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Criar nota"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitarefas"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Usar a tela dividida com o app à direita"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Usar a tela dividida com o app à esquerda"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Mudar para tela cheia"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Mudar para o app à direita ou abaixo ao usar a tela dividida"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Mudar para o app à esquerda ou acima ao usar a tela dividida"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Com a tela dividida: substituir um app por outro"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Localize o smartphone com o Encontre Meu Dispositivo mesmo se ele estiver desligado"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Desligando…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Ver etapas de cuidado"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ir para a página inicial"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ver os apps recentes"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Concluído"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Voltar"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Deslize para a esquerda ou direita com 3 dedos no touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Legal!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Você concluiu o gesto para voltar."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ir para a página inicial"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Deslize para cima com 3 dedos no touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Muito bem!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Você concluiu o gesto para acessar a tela inicial"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ver os apps recentes"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Deslize para cima com 3 dedos e mantenha"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Muito bem!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Você concluiu o gesto para ver os apps recentes."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ver todos os apps"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pressione a tecla de ação no teclado"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Muito bem!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Você concluiu o gesto para ver todos os apps"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animação do tutorial. Clique para pausar ou retomar a reprodução."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Luz de fundo do teclado"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nível %1$d de %2$d"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ea320a1..7664145 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgeturi"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Pentru a adăuga comanda rapidă Widgeturi, verifică dacă opțiunea Afișează widgeturi pe ecranul de blocare este activată în setări."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Setări"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Butonul Afișează screensaverul"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prin satelit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Apeluri de urgență sau SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"fără semnal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"o bară"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"două bare"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"trei bare"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"patru bare"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"semnal complet"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Se afișează în partea de sus a notificărilor pentru conversații și ca fotografie de profil pe ecranul de blocare, apare ca un balon, întrerupe funcția Nu deranja"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritate"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu acceptă funcții pentru conversații"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Trimite feedback despre pachet"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Aceste notificări nu pot fi modificate."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Notificările pentru apeluri nu pot fi modificate."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Acest grup de notificări nu poate fi configurat aici"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ecranul de blocare"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Creează o notă"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Folosește ecranul împărțit cu aplicația în dreapta"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Folosește ecranul împărțit cu aplicația în stânga"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Treci la ecran complet"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Treci la aplicația din dreapta sau de mai jos cu ecranul împărțit"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Treci la aplicația din stânga sau de mai sus cu ecranul împărțit"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"În modul ecran împărțit: înlocuiește o aplicație cu alta"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meniul de pornire"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ecran de blocare"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Poți localiza telefonul folosind aplicația Găsește-mi dispozitivul chiar dacă este închis"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Se închide…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Vezi pașii pentru îngrijire"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vezi pașii pentru îngrijire"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Înapoi la pagina de pornire"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Vezi aplicațiile recente"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Gata"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Înapoi"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Glisează la stânga sau la dreapta cu trei degete pe touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bravo!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ai finalizat gestul Înapoi."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Înapoi la pagina de pornire"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Glisează în sus cu trei degete oriunde pe touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Excelent!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ai finalizat gestul „înapoi la pagina de pornire”"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Vezi aplicațiile recente"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Glisează în sus și ține apăsat cu trei degete pe touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Excelent!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ai finalizat gestul pentru afișarea aplicațiilor recente."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Vezi toate aplicațiile"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Apasă tasta de acțiuni de pe tastatură"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Felicitări!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Ai finalizat gestul pentru afișarea tuturor aplicațiilor"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Tutorial animat, dă clic pentru a întrerupe și a relua redarea."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Iluminarea din spate a tastaturii"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivelul %1$d din %2$d"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index f785936..19ccb08 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Виджеты"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Чтобы создать ярлык \"Виджеты\", убедитесь, что в настройках включена функция \"Показывать виджеты на заблокированном экране\"."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Настройки"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Показать заставку\""</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутниковый SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстренные вызовы или спутниковый SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"нет сигнала"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"одно деление"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"два деления"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"три деления"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"четыре деления"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"надежный сигнал"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Появляется в верхней части уведомлений о сообщениях, в виде всплывающего чата, а также в качестве фото профиля на заблокированном экране, прерывает режим \"Не беспокоить\"."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Отправить отзыв о сгруппированных уведомлениях"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Эти уведомления нельзя изменить."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Уведомления о звонках нельзя изменить."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Эту группу уведомлений нельзя настроить здесь."</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокировать экран"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Создать заметку"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Многозадачность"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Разделить экран и поместить открытое приложение справа"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Разделить экран и поместить открытое приложение слева"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Включить полноэкранный режим"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Перейти к приложению справа или внизу на разделенном экране"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Перейти к приложению слева или вверху на разделенном экране"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"В режиме разделения экрана заменить одно приложение другим"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки питания"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокированный экран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"С помощью приложения \"Найти устройство\" вы можете узнать местоположение телефона, даже когда он выключен."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Выключение…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Подробнее о действиях при перегреве…"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Подробнее о действиях при перегреве…"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"На главный экран"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Просмотр недавних приложений"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Проведите тремя пальцами влево или вправо по сенсорной панели."</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Отлично!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Вы выполнили жест для перехода назад."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"На главный экран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Проведите тремя пальцами вверх по сенсорной панели."</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Отлично!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Вы выполнили жест для перехода на главный экран."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Просмотр недавних приложений"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Проведите вверх по сенсорной панели тремя пальцами и удерживайте."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Отлично!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Вы выполнили жест для просмотра недавних приложений."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Все приложения"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Нажмите клавишу действия на клавиатуре."</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Блестяще!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Вы выполнили жест для просмотра всех приложений."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Анимация в руководстве. Нажмите, чтобы приостановить или продолжить воспроизведение."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Подсветка клавиатуры"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Уровень %1$d из %2$d"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 68cdef7..516b2ae 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"විජට්"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"විජට්\" කෙටිමඟ එක් කිරීමට, සැකසීම් තුළ \"අගුළු තිරයෙහි විජට් පෙන්වන්න\" සබල කර ඇති බවට වග බලා ගන්න."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"සැකසීම්"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"තිර සුරැකුම් බොත්තම පෙන්වන්න"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්‍රිකාව, සම්බන්ධතාවය තිබේ"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"චන්ද්‍රිකා SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"හදිසි ඇමතුම් හෝ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"සංඥාව නැත"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"තීරු එකක්"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"තීරු දෙකයි"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"තීරු තුනයි"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"තීරු හතරක්"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"සංඥාව පිරී ඇත"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්‍රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්‍රවේශමෙන් ඉදිරියට යන්න."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"සංවාද දැනුම්දීම්වල ඉහළින්ම සහ අගුලු තිරයේ ඇති පැතිකඩ පින්තූරයක් ලෙස පෙන්වයි, බුබුළක් ලෙස දිස් වේ, බාධා නොකරන්න සඳහා බාධා කරයි"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ප්‍රමුඛතාව"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> සංවාද විශේෂාංගවලට සහාය නොදක්වයි"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"බණ්ඩල් ප්‍රතිපෝෂණ ලබා දෙන්න"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"මෙම දැනුම්දීම් වෙනස් කළ නොහැක."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"ඇමතුම් දැනුම්දීම් වෙනස් කළ නොහැකිය."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"මෙම දැනුම්දීම් සමූහය මෙහි වින්‍යාස කළ නොහැක"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"තිරය අගුළු දමන්න"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"සටහනක් ගන්න"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"බහුකාර්ය"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"දකුණේ යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"වම් පැත්තේ යෙදුම සමග බෙදීම් තිරය භාවිතා කරන්න"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"සම්පූර්ණ තිරයට මාරු වන්න"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"බෙදුම් තිරය භාවිත කරන අතරතුර දකුණේ හෝ පහළින් ඇති යෙදුමට මාරු වන්න"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"බෙදුම් තිරය භාවිත කරන අතරතුර වමේ හෝ ඉහළ ඇති යෙදුමට මාරු වන්න"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"බෙදුම් තිරය අතරතුර: යෙදුමක් එකකින් තවත් එකක් ප්‍රතිස්ථාපනය කරන්න"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"බල මෙනුව"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"අගුලු තිරය"</string>
-    <string name="finder_active" msgid="7907846989716941952">"බලය ක්‍රියාවිරහිත වූ විට පවා ඔබට මගේ උපාංගය සෙවීම මගින් මෙම දුරකථනය සොයාගත හැක"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"වසා දමමින්…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"රැකවරණ පියවර බලන්න"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"රැකවරණ පියවර බලන්න"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"මුල් පිටුවට යන්න"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"මෑත යෙදුම් බලන්න"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"නිමයි"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ආපස්සට යන්න"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ඔබේ ස්පර්ශ පුවරුව මත ඇඟිලි තුනක් භාවිතයෙන් වමට හෝ දකුණට ස්වයිප් කරන්න"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"කදිමයි!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"ඔබ ආපසු යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"මුල් පිටුවට යන්න"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ඔබේ ස්පර්ශ පුවරුවේ ඇඟිලි තුනකින් ඉහළට ස්වයිප් කරන්න"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"අනර්ඝ වැඩක්!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"ඔබ මුල් පිටුවට යාමේ ඉංගිතය සම්පූර්ණ කරන ලදි"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"මෑත යෙදුම් බලන්න"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ඉහළට ස්වයිප් කර ඔබේ ස්පර්ශ පුවරුව මත ඇඟිලි තුනක් භාවිත කර රඳවාගෙන සිටින්න"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"අනර්ඝ වැඩක්!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ඔබ මෑත යෙදුම් ඉංගිත බැලීම සම්පූර්ණ කර ඇත."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"සියලු යෙදුම් බලන්න"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"ඔබේ යතුරු පුවරුවේ ක්‍රියාකාරී යතුර ඔබන්න"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"හොඳින් කළා!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"ඔබ සියලු යෙදුම් ඉංගිත බැලීම සම්පූර්ණ කර ඇත"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"නිබන්ධන සජීවීකරණය, ක්‍රීඩාව විරාම කිරීමට සහ නැවත ආරම්භ කිරීමට ක්ලික් කරන්න."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"යතුරු පුවරු පසු ආලෝකය"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dන් %1$d වැනි මට්ටම"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 552b2e3..1b2dc5a 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -454,7 +454,7 @@
     <string name="zen_mode_off" msgid="1736604456618147306">"Vypnuté"</string>
     <string name="zen_mode_set_up" msgid="8231201163894922821">"Nenastavené"</string>
     <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"Správa v nastaveniach"</string>
-    <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žiadne aktívne režimy}=1{{mode} je aktívny}few{# režimy sú aktívne}many{# modes are active}other{# režimov je aktívnych}}"</string>
+    <string name="zen_mode_active_modes" msgid="1625850411578488856">"{count,plural, =0{Žiadne aktívne režimy}=1{Aktívny režim {mode}}few{# aktívne režimy}many{# modes are active}other{# aktívnych režimov}}"</string>
     <string name="zen_priority_introduction" msgid="3159291973383796646">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky, pripomenutia, udalosti a volajúci, ktorých určíte. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string>
     <string name="zen_alarms_introduction" msgid="3987266042682300470">"Nebudú vás vyrušovať zvuky ani vibrácie, iba budíky. Budete naďalej počuť všetko, čo sa rozhodnete prehrať, ako napríklad hudbu, videá a hry."</string>
     <string name="zen_priority_customize_button" msgid="4119213187257195047">"Prispôsobiť"</string>
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Miniaplikácie"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ak chcete pridať odkaz Miniaplikácie, uistite sa, že v nastaveniach je zapnutá možnosť Zobrazovať miniaplikácie na uzamknutej obrazovke."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Nastavenia"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Zobraziť tlačidlo šetriča obrazovky"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Pomoc cez satelit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tiesňové volania alebo pomoc v tiesni"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"žiadny signál"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"jedna čiarka"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dve čiarky"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tri čiarky"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"štyri čiarky"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"plný signál"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Zobrazuje sa ako bublina v hornej časti upozornení konverzácie a profilová fotka na uzamknutej obrazovke, preruší režim bez vyrušení"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritné"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nepodporuje funkcie konverzácie"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Poskytnúť spätnú väzbu k balíku"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Tieto upozornenia sa nedajú upraviť."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Upozornenia na hovory sa nedajú upraviť."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Túto skupinu upozornení nejde na tomto mieste konfigurovať"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Uzamknutie obrazovky"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Napísanie poznámky"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Rozdelenie obrazovky, aktuálna aplikácia vpravo"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Rozdelenie obrazovky, aktuálna aplikácia vľavo"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Prepnutie na celú obrazovku"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Prechod na aplikáciu vpravo alebo dole pri rozdelenej obrazovke"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Prechod na aplikáciu vľavo alebo hore pri rozdelenej obrazovke"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Počas rozdelenej obrazovky: nahradenie aplikácie inou"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ponuka vypínača"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Uzamknutá obrazovka"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Pomocou funkcie Nájdi moje zariadenie môžete zistiť polohu tohto telefónu, aj keď je vypnutý"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Vypína sa…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Zobraziť opatrenia"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobraziť opatrenia"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Prejsť na plochu"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Zobrazenie nedávnych aplikácií"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Hotovo"</string>
-    <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejsť späť"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
+    <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Prejdenie späť"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Potiahnite troma prstami na touchpade doľava alebo doprava"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Výborne!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Použili ste gesto na prechod späť."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Prechod na plochu"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Potiahnite troma prstami na touchpade nahor"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Skvelé!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Použili ste gesto na prechod na plochu."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Zobrazenie nedávnych aplikácií"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Potiahnite troma prstami na touchpade nahor a pridržte"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Skvelé!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Použili ste gesto na zobrazenie nedávnych aplikácií."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Zobrazenie všetkých aplikácií"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Stlačte na klávesnici akčný kláves"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Dobre!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Použili ste gesto na zobrazenie všetkých aplikácií."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Výuková animácia, kliknutím pozastavíte alebo obnovíte prehrávanie."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Podsvietenie klávesnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. úroveň z %2$d"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 33d400c..76ce78c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prek satelita"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Klici v sili ali SOS prek satelita"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ni signala"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ena črtica"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dve črtici"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tri črtice"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"štiri črtice"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"poln signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Prikaz v obliki oblačka na vrhu razdelka z obvestili za pogovor in kot profilna slika na zaklenjenem zaslonu, preglasitev načina Ne moti."</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prednostno"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podpira pogovornih funkcij."</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Pošiljanje povratnih informacij v paketu"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Za ta obvestila ni mogoče spremeniti nastavitev."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Obvestil o klicih ni mogoče spreminjati."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Te skupine obvestil ni mogoče konfigurirati tukaj"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaklepanje zaslona"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Ustvarjanje zapiska"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Večopravilnost"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Uporaba razdeljenega zaslona z aplikacijo na desni"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Uporaba razdeljenega zaslona z aplikacijo na levi"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Preklop na celozaslonski način"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Preklop na aplikacijo desno ali spodaj med uporabo razdeljenega zaslona"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Preklop na aplikacijo levo ali zgoraj med uporabo razdeljenega zaslona"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Pri razdeljenem zaslonu: medsebojna zamenjava aplikacij"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni za vklop/izklop"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaklenjen zaslon"</string>
-    <string name="finder_active" msgid="7907846989716941952">"S storitvijo Poišči mojo napravo lahko ta telefon poiščete, tudi če je izklopljen"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Zaustavljanje …"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Oglejte si navodila za ukrepanje"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Oglejte si navodila za ukrepanje"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Pomik na začetni zaslon"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Ogled nedavnih aplikacij"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Končano"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Nazaj"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Na sledilni ploščici s tremi prsti povlecite levo ali desno"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Odlično!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Izvedli ste potezo za pomik nazaj."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pomik na začetni zaslon"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Na sledilni ploščici s tremi prsti povlecite navzgor"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Odlično!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Izvedli ste potezo za pomik na začetni zaslon"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Ogled nedavnih aplikacij"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Na sledilni ploščici s tremi prsti povlecite navzgor in pridržite"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Odlično!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Izvedli ste potezo za ogled nedavnih aplikacij."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Ogled vseh aplikacij"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pritisnite tipko za dejanja na tipkovnici"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Odlično!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Izvedli ste potezo za ogled vseh aplikacij"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacija v vadnici, kliknite za začasno zaustavitev in nadaljevanje predvajanja."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Osvetlitev tipkovnice"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Stopnja %1$d od %2$d"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index ce7c9c0..dd13cff 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Miniaplikacionet"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Për të shtuar shkurtoren e \"Miniaplikacioneve\", sigurohu që \"Shfaq miniaplikacionet në ekranin e kyçjes\" të jetë aktivizuar te cilësimet."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Cilësimet"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Shfaq butonin e mbrojtësit të ekranit"</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Njoftimet"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Bisedat"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Pastro të gjitha njoftimet në heshtje"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Hap cilësimet e njoftimeve"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Njoftimet janë vendosur në pauzë nga modaliteti \"Mos shqetëso\""</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Asnjë njoftim}=1{Njoftimet u vendosën në pauzë nga {mode}}=2{Njoftimet u vendosën në pauzë nga {mode} dhe një modalitet tjetër}other{Njoftimet u vendosën në pauzë nga {mode} dhe # modalitete të tjera}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Fillo tani"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satelitor"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Telefonatat e urgjencës ose SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"nuk ka sinjal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"një vijë"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dy vija"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tre vija"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"katër vija"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"sinjal i plotë"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Shfaqet në krye të njoftimeve të bisedës dhe si fotografia e profilit në ekranin e kyçjes, shfaqet si flluskë dhe ndërpret modalitetin \"Mos shqetëso\""</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Me përparësi"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mbështet veçoritë e bisedës"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Jep komente për paketën"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Këto njoftime nuk mund të modifikohen."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Njoftimet e telefonatave nuk mund të modifikohen."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ky grup njoftimesh nuk mund të konfigurohet këtu"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekrani i kyçjes"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Mbaj një shënim"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Kryerja e shumë detyrave"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Përdor ekranin e ndarë me aplikacionin në të djathtë"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Përdor ekranin e ndarë me aplikacionin në të majtë"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Kalo në ekran të plotë"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Kalo tek aplikacioni djathtas ose poshtë kur përdor ekranin e ndarë"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Kalo tek aplikacioni në të majtë ose sipër kur përdor ekranin e ndarë"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Gjatë ekranit të ndarë: zëvendëso një aplikacion me një tjetër"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyja e energjisë"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekrani i kyçjes"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Mund ta gjesh këtë telefon me \"Gjej pajisjen time\" edhe kur është i fikur"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Po fiket…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Shiko hapat për kujdesin"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Shiko hapat për kujdesin"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Shko tek ekrani bazë"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Shiko aplikacionet e fundit"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"U krye"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Kthehu prapa"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Rrëshqit shpejt majtas ose djathtas duke përdorur tre gishta në bllokun me prekje"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bukur!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"E ke përfunduar gjestin e kthimit prapa."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Shko tek ekrani bazë"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Rrëshqit shpejt lart me tre gishta në bllokun me prekje"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Punë e shkëlqyer!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"E ke përfunduar gjestin e kalimit tek ekrani bazë"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Shiko aplikacionet e fundit"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Rrëshqit shpejt lart dhe mbaj shtypur me tre gishta në bllokun me prekje"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Punë e shkëlqyer!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Përfundove gjestin për shikimin e aplikacioneve të fundit."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Shiko të gjitha aplikacionet"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Shtyp tastin e veprimit në tastierë"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Shumë mirë!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Përfundove gjestin për shikimin e të gjitha aplikacioneve"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animacioni udhëzues. Kliko për të vendosur në pauzë dhe për të vazhduar luajtjen."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Drita e sfondit e tastierës"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Niveli: %1$d nga %2$d"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8ae5446..5693956 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хитна помоћ преко сателита"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Хитни позиви или хитна помоћ"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"нема сигнала"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"једна црта"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"две црте"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"три црте"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"четири црте"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"сигнал је најјачи"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Приказује се у врху обавештења о конверзацијама и као слика профила на закључаном екрану, појављује се као облачић, прекида режим Не узнемиравај"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не подржава функције конверзације"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Пружите повратне информације о скупу"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ова обавештења не могу да се мењају."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Обавештења о позивима не могу да се мењају."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ова група обавештења не може да се конфигурише овде"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Откључавање екрана"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Направи белешку"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Обављање више задатака истовремено"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Користи подељени екран са апликацијом с десне стране"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Користи подељени екран са апликацијом с леве стране"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Пређи на режим преко целог екрана"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Пређи у апликацију здесна или испод док је подељен екран"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Пређите у апликацију слева или изнад док користите подељени екран"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"У режиму подељеног екрана: замена једне апликације другом"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени дугмета за укључивање"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Закључан екран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Можете да лоцирате овај телефон помоћу услуге Пронађи мој уређај чак и када је искључен"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Искључује се…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Погледајте упозорења"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Погледајте упозорења"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Иди на почетни екран"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Прикажи недавно коришћене апликације"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Превуците улево или удесно са три прста на тачпеду"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Супер!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Довршили сте покрет за повратак."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Иди на почетни екран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Превуците нагоре са три прста на тачпеду"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Одлично!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Довршили сте покрет за повратак на почетну страницу."</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Прикажи недавно коришћене апликације"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Превуците нагоре и задржите са три прста на тачпеду"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Одлично!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Довршили сте покрет за приказивање недавно коришћених апликација."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Прикажи све апликације"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Притисните тастер радњи на тастатури"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Одлично!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Довршили сте покрет за приказивање свих апликација."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Анимација водича, кликните да бисте паузирали и наставили репродукцију."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Позадинско осветљење тастатуре"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%1$d. ниво од %2$d"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index dcb1955b..7d1f755 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widgetar"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Om du vill lägga till genvägen Widgetar måste du se till att Visa widgetar på låsskärmen är aktiverat i inställningarna."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Inställningar"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Visa skärmsläckarknappen"</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Aviseringar"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Konversationer"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Rensa alla ljudlösa aviseringar"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Öppna aviseringsinställningarna"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Aviseringar har pausats via Stör ej"</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Inga aviseringar}=1{Aviseringar har pausats av {mode}}=2{Aviseringar har pausats av {mode} och ett annat läge}other{Aviseringar har pausats av {mode} och # andra lägen}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Starta nu"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-larm via satellit"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nödsamtal eller SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ingen signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"en stapel"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"två staplar"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tre staplar"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"fyra staplar"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"full signalstyrka"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Visas högst upp i konversationsaviseringarna och som profilbild på låsskärmen, visas som bubbla, åsidosätter Stör ej"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte stöd för konversationsfunktioner"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Ge feedback om paket"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Det går inte att ändra de här aviseringarna."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Det går inte att ändra samtalsaviseringarna."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Den här aviseringsgruppen kan inte konfigureras här"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Lås skärmen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Anteckna"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multikörning"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Använd delad skärm med appen till höger"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Använd delad skärm med appen till vänster"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Byt till helskärm"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Byt till appen till höger eller nedanför när du använder delad skärm"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Byt till appen till vänster eller ovanför när du använder delad skärm"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Med delad skärm: ersätt en app med en annan"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Startmeny"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sida <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Låsskärm"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Du kan hitta den här telefonen med Hitta min enhet även när den är avstängd"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Avslutar …"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Visa alla skötselråd"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Visa alla skötselråd"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Återvänd till startsidan"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Se de senaste apparna"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Klar"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Tillbaka"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Svep åt vänster eller höger med tre fingrar på styrplattan"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Bra!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Du är klar med rörelsen för att gå tillbaka."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Återvänd till startskärmen"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Svep uppåt med tre fingrar på styrplattan"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Bra jobbat!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Du är klar med rörelsen för att öppna startskärmen"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Se de senaste apparna"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Svep uppåt med tre fingrar på styrplattan och håll kvar"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Bra jobbat!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Du är klar med rörelsen för att se de senaste apparna."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Visa alla appar"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Tryck på åtgärdstangenten på tangentbordet"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Bra gjort!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Du är klar med rörelsen för att se alla apparna."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation för guiden: Klicka för att pausa och återuppta uppspelningen."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Bakgrundsbelysning för tangentbord"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Nivå %1$d av %2$d"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index cd2c448..a17d645 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Wijeti"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ili uweke njia ya mkato ya \"Wijeti\", hakikisha kuwa kitufe cha \"Onyesha wijeti kwenye skrini iliyofungwa\" kimewashwa katika mipangilio."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Mipangilio"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Kitufe cha “Onyesha taswira ya skrini”"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Msaada kupitia Setilaiti"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Simu za dharura"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"hakuna mtandao"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"upau mmoja"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"pau mbili"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"pau tatu"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"pau nne"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"mtandao ni thabiti kabisa"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Huonyeshwa kwenye sehemu ya juu ya arifa za mazungumzo na kama picha ya wasifu kwenye skrini iliyofungwa. Huonekana kama kiputo na hukatiza kipengele cha Usinisumbue"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Kipaumbele"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> haitumii vipengele vya mazungumzo"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Toa Maoni kuhusu Kifurushi"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Arifa hizi haziwezi kubadilishwa."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arifa za simu haziwezi kubadilishwa."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Kikundi hiki cha arifa hakiwezi kuwekewa mipangilio hapa"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Funga skrini"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Andika dokezo"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Majukumu mengi"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kulia"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Tumia hali ya kugawa skrini na programu ya sasa iwe upande wa kushoto"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Badilisha utumie skrini nzima"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Badilisha ili uende kwenye programu iliyo kulia au chini unapotumia hali ya kugawa skrini"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Badilisha uende kwenye programu iliyo kushoto au juu unapotumia hali ya kugawa skrini"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ukigawanya skrini: badilisha kutoka programu moja hadi nyingine"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyu ya kuzima/kuwasha"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Skrini iliyofungwa"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Unaweza kutambua mahali ilipo simu hii ukitumia programu ya Tafuta Kifaa Changu hata kama simu hiyo imezimwa"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Inazima…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Angalia hatua za utunzaji"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Angalia hatua za utunzaji"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Nenda kwenye ukurasa wa mwanzo"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Angalia programu za hivi majuzi"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Nimemaliza"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Rudi nyuma"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Telezesha vidole vitatu kushoto au kulia kwenye padi yako ya kugusa"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Safi!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Umekamilisha mafunzo ya miguso ya kurudi nyuma."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Nenda kwenye skrini ya kwanza"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Telezesha vidole vitatu juu kwenye padi yako ya kugusa"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Kazi nzuri!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Umeweka ishara ya kwenda kwenye skrini ya kwanza"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Angalia programu za hivi majuzi"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Telezesha vidole vitatu juu kisha ushikilie kwenye padi yako ya kugusa"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Kazi nzuri!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Umekamilisha mafunzo ya mguso wa kuangalia programu za hivi majuzi."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Angalia programu zote"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Bonyeza kitufe cha vitendo kwenye kibodi yako"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Vizuri sana!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Umekamilisha mafunzo ya mguso wa kuangalia programu zote"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Uhuishaji wa mafunzo, bofya ili usitishe na uendelee kucheza."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Mwanga chini ya kibodi"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Kiwango cha %1$d kati ya %2$d"</string>
diff --git a/packages/SystemUI/res/values-sw600dp-long/config.xml b/packages/SystemUI/res/values-sw600dp-long/config.xml
new file mode 100644
index 0000000..92e3469
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp-long/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- The number of columns in the Split Shade QuickSettings -->
+    <integer name="quick_settings_split_shade_num_columns">6</integer>
+</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index b438315..ab0f788 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -19,7 +19,7 @@
 
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
     <!-- The maximum number of rows in the QuickSettings -->
     <integer name="quick_settings_max_rows">4</integer>
 
@@ -51,7 +51,9 @@
     ignored. -->
     <string-array name="config_keyguardQuickAffordanceDefaults" translatable="false">
         <item>bottom_start:home</item>
-        <item>bottom_end:create_note</item>
+        <!-- TODO(b/384119565): revisit decision on defaults -->
+        <item android:featureFlag="!com.android.systemui.glanceable_hub_v2_resources">bottom_end:create_note</item>
+        <item android:featureFlag="com.android.systemui.glanceable_hub_v2_resources">bottom_end:glanceable_hub</item>
     </string-array>
 
     <!-- Whether volume panel should use the large screen layout or not -->
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index ce630bb..3270e5e 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"விட்ஜெட்கள்"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"“விட்ஜெட்கள்” ஷார்ட்கட்டைச் சேர்க்க, அமைப்புகளில் “பூட்டுத் திரையில் விட்ஜெட்களைக் காட்டுதல்” அமைப்பு இயக்கப்பட்டிருப்பதை உறுதிசெய்துகொள்ளுங்கள்."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"அமைப்புகள்"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"ஸ்கிரீன் சேவரைக் காட்டும் பட்டன்"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"சாட்டிலைட் SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"அவசர அழைப்புகள் அல்லது SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"சிக்னல் இல்லை"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ஒரு கோடு"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"இரண்டு கோடுகள்"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"மூன்று கோடுகள்"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"நான்கு கோடுகள்"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"சிக்னல் முழுமையாக உள்ளது"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"உரையாடல் அறிவிப்புகளின் மேற்பகுதியில் காட்டப்படும், திரை பூட்டப்பட்டிருக்கும்போது சுயவிவரப் படமாகக் காட்டப்படும், குமிழாகத் தோன்றும், தொந்தரவு செய்ய வேண்டாம் அம்சம் இயக்கப்பட்டிருக்கும்போதும் காட்டப்படும்"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"முன்னுரிமை"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"உரையாடல் அம்சங்களை <xliff:g id="APP_NAME">%1$s</xliff:g> ஆதரிக்காது"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"மொத்தமாகக் கருத்தை வழங்கு"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"இந்த அறிவிப்புகளை மாற்ற இயலாது."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"அழைப்பு அறிவிப்புகளை மாற்ற முடியாது."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"இந்த அறிவுப்புக் குழுக்களை இங்கே உள்ளமைக்க இயலாது"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"பூட்டுத் திரை"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"குறிப்பெடுத்தல்"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"பல வேலைகளைச் செய்தல்"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ஆப்ஸ் வலதுபுறம் வரும்படி திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ஆப்ஸ் இடதுபுறம் வரும்படி திரைப் பிரிப்பைப் பயன்படுத்துதல்"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"முழுத்திரைக்கு மாற்றுதல்"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது வலது/கீழ் உள்ள ஆப்ஸுக்கு மாறுதல்"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"திரைப் பிரிப்பைப் பயன்படுத்தும்போது இடது/மேலே உள்ள ஆப்ஸுக்கு மாறுதல்"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"திரைப் பிரிப்பின்போது: ஓர் ஆப்ஸுக்குப் பதிலாக மற்றொன்றை மாற்றுதல்"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"பவர் மெனு"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"லாக் ஸ்கிரீன்"</string>
-    <string name="finder_active" msgid="7907846989716941952">"மொபைல் பவர் ஆஃப் செய்யப்பட்டிருக்கும்போதும் Find My Device மூலம் அதன் இருப்பிடத்தைக் கண்டறியலாம்"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"ஷட் டவுன் ஆகிறது…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"முகப்பிற்குச் செல்"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"சமீபத்திய ஆப்ஸைக் காட்டுதல்"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"முடிந்தது"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"பின்செல்"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"உங்கள் டச்பேடில் மூன்று விரல்களால் இடது அல்லது வலதுபுறம் ஸ்வைப் செய்யவும்"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"அருமை!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"பின்செல்வதற்கான சைகையை நிறைவுசெய்துவிட்டீர்கள்."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"முகப்பிற்குச் செல்"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்யவும்"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"அருமை!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"முகப்புக்குச் செல்வதற்கான சைகைப் பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"சமீபத்திய ஆப்ஸைக் காட்டுதல்"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"உங்கள் டச்பேடில் மூன்று விரல்களால் மேல்நோக்கி ஸ்வைப் செய்து பிடிக்கவும்"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"அருமை!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"சமீபத்தில் பயன்படுத்திய ஆப்ஸுக்கான சைகை பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"அனைத்து ஆப்ஸையும் காட்டு"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"உங்கள் கீபோர்டில் ஆக்‌ஷன் பட்டனை அழுத்தவும்"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"அருமை!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"அனைத்து ஆப்ஸையும் பார்ப்பதற்கான சைகை பயிற்சியை நிறைவுசெய்துவிட்டீர்கள்"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"பயிற்சி அனிமேஷன், இடைநிறுத்தவும் மீண்டும் இயக்கவும் கிளிக் செய்யலாம்."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"கீபோர்டு பேக்லைட்"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"நிலை, %2$d இல் %1$d"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 20d4cf7..ea02e4f 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"ఎమర్జెన్సీ శాటిలైట్ సహాయం"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ఎమర్జెన్సీ కాల్స్ లేదా SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"సిగ్నల్ లేదు"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"సిగ్నల్ ఒక బార్ ఉంది"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"సిగ్నల్ రెండు బార్‌లు ఉన్నాయి"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"సిగ్నల్ మూడు బార్‌లు ఉన్నాయి"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"సిగ్నల్ నాలుగు బార్‌లు ఉన్నాయి"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"సిగ్నల్ పూర్తిగా ఉంది"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్‌"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్‌ఫేస్‌ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"సంభాషణ నోటిఫికేషన్‌ల ఎగువున, లాక్ స్క్రీన్‌లో ప్రొఫైల్ ఫోటో‌గా చూపిస్తుంది, బబుల్‌గా కనిపిస్తుంది, \'అంతరాయం కలిగించవద్దు\'ను అంతరాయం కలిగిస్తుంది"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> సంభాషణ ఫీచర్‌లను సపోర్ట్ చేయదు"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"బండిల్ ఫీడ్‌బ్యాక్‌ను అందించండి"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ఈ నోటిఫికేషన్‌లను ఎడిట్ చేయడం వీలుపడదు."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"కాల్ నోటిఫికేషన్‌లను ఎడిట్ చేయడం సాధ్యం కాదు."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"ఈ నోటిఫికేషన్‌ల గ్రూప్‌ను ఇక్కడ కాన్ఫిగర్ చేయలేము"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"లాక్ స్క్రీన్"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"నోట్‌ను రాయండి"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"మల్టీ-టాస్కింగ్"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"కుడి వైపు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఉపయోగించండి"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ఎడమ వైపు ప్రస్తుత యాప్‌తో స్ప్లిట్ స్క్రీన్‌ను ఉపయోగించండి"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"ఫుల్ స్క్రీన్‌కు మారండి"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు కుడి లేదా కింద యాప్‌నకు మారండి"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"స్ప్లిట్ స్క్రీన్ ఉపయోగిస్తున్నప్పుడు ఎడమ లేదా పైన యాప్‌నకు మారండి"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"స్ప్లిట్ స్క్రీన్ సమయంలో: ఒక దాన్నుండి మరో దానికి యాప్ రీప్లేస్ చేయండి"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"పవర్ మెనూ"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"లాక్ స్క్రీన్"</string>
-    <string name="finder_active" msgid="7907846989716941952">"పవర్ ఆఫ్‌లో ఉన్నప్పుడు కూడా మీరు Find My Deviceతో ఈ ఫోన్‌ను గుర్తించవచ్చు"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"షట్ డౌన్ చేయబడుతోంది…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string>
@@ -1461,27 +1463,37 @@
     <string name="launch_touchpad_tutorial_notification_title" msgid="2243780062772196901">"మీ టచ్‌ప్యాడ్‌ను ఉపయోగించి నావిగేట్ చేయండి"</string>
     <string name="launch_touchpad_tutorial_notification_content" msgid="7931085031240753226">"టచ్‌ప్యాడ్ సంజ్ఞల గురించి తెలుసుకోండి"</string>
     <string name="launch_keyboard_touchpad_tutorial_notification_title" msgid="1940023776496198762">"మీ కీబోర్డ్, టచ్‌ప్యాడ్‌ను ఉపయోగించి నావిగేట్ చేయండి"</string>
-    <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"టచ్‌ప్యాడ్ సంజ్ఞలు, కీబోర్డ్ షార్ట్‌కట్‌లు, అలాగే మరిన్నింటిని గురించి తెలుసుకోండి"</string>
+    <string name="launch_keyboard_touchpad_tutorial_notification_content" msgid="1780725168171929365">"టచ్‌ప్యాడ్ సంజ్ఞలు, కీబోర్డ్ షార్ట్‌కట్‌లు మొదలైన వాటి గురించి తెలుసుకోండి"</string>
     <string name="touchpad_tutorial_back_gesture_button" msgid="3104716365403620315">"వెనుకకు వెళ్లండి"</string>
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"మొదటి ట్యాబ్‌కు వెళ్లండి"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ఇటీవలి యాప్‌లను చూడండి"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"పూర్తయింది"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"వెనుకకు"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"మీ టచ్‌ప్యాడ్‌లో మూడు వేళ్లను ఉపయోగించి ఎడమ వైపునకు లేదా కుడి వైపునకు స్వైప్ చేయండి"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"సూపర్!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"తిరిగి వెనుకకు వెళ్ళడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్‌ను మీరు పూర్తి చేశారు."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"మొదటి ట్యాబ్‌కు వెళ్లండి"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"మీ టచ్‌ప్యాడ్‌పై మూడు వేళ్లతో పైకి స్వైప్ చేయండి"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"చక్కగా పూర్తి చేశారు!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"మీరు మొదటి స్క్రీన్‌కు వెళ్లే సంజ్ఞను పూర్తి చేశారు"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ఇటీవలి యాప్‌లను చూడండి"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"మీ టచ్‌ప్యాడ్‌లో మూడు వేళ్లను ఉపయోగించి పైకి స్వైప్ చేసి, హోల్డ్ చేయండి"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"చక్కగా పూర్తి చేశారు!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"ఇటీవలి యాప్‌లను చూడడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్‌ను మీరు పూర్తి చేశారు."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"అన్ని యాప్‌లను చూడండి"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"మీ కీబోర్డ్‌లో యాక్షన్ కీని నొక్కండి"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"చక్కగా చేశారు!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"అన్ని యాప్‌లను చూడడానికి ఉపయోగించే సంజ్ఞకు సంబంధించిన ట్యుటోరియల్‌ను మీరు పూర్తి చేశారు"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ట్యుటోరియల్ యానిమేషన్, పాజ్ చేసి, మళ్లీ ప్లే చేయడానికి క్లిక్ చేయండి."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"కీబోర్డ్ బ్యాక్‌లైట్"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"%2$dలో %1$dవ స్థాయి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index d438e44..f8c4327 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ดาวเทียม"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"การโทรฉุกเฉินหรือ SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ไม่มีสัญญาณ"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 ขีด"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 ขีด"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 ขีด"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 ขีด"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"สัญญาณเต็ม"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"แสดงที่ด้านบนของการแจ้งเตือนการสนทนาและเป็นรูปโปรไฟล์บนหน้าจอล็อก ปรากฏเป็นบับเบิล แสดงในโหมดห้ามรบกวน"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"สำคัญ"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่รองรับฟีเจอร์การสนทนา"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"แสดงความคิดเห็นเกี่ยวกับแพ็กเกจ"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"แก้ไขการแจ้งเตือนเหล่านี้ไม่ได้"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"แก้ไขการแจ้งเตือนสายเรียกเข้าไม่ได้"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"การแจ้งเตือนกลุ่มนี้กำหนดค่าที่นี่ไม่ได้"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"ล็อกหน้าจอ"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"จดโน้ต"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"การทํางานหลายอย่างพร้อมกัน"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"ใช้โหมดแยกหน้าจอโดยให้แอปอยู่ด้านขวา"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"ใช้โหมดแยกหน้าจอโดยให้แอปอยู่ด้านซ้าย"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"เปลี่ยนเป็นแบบเต็มหน้าจอ"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"เปลี่ยนไปใช้แอปทางด้านขวาหรือด้านล่างขณะใช้โหมดแยกหน้าจอ"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"เปลี่ยนไปใช้แอปทางด้านซ้ายหรือด้านบนขณะใช้โหมดแยกหน้าจอ"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"ระหว่างใช้โหมดแยกหน้าจอ: เปลี่ยนแอปหนึ่งเป็นอีกแอปหนึ่ง"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"เมนูเปิด/ปิด"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"หน้าจอล็อก"</string>
-    <string name="finder_active" msgid="7907846989716941952">"คุณจะหาตำแหน่งของโทรศัพท์นี้ได้ด้วยแอปหาอุปกรณ์ของฉันแม้จะปิดเครื่องอยู่ก็ตาม"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"กำลังปิด…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"ดูขั้นตอนในการดูแลรักษา"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ดูขั้นตอนในการดูแลรักษา"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ไปที่หน้าแรก"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"ดูแอปล่าสุด"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"เสร็จสิ้น"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"ลองอีกครั้งนะ"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"ย้อนกลับ"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวาบนทัชแพด"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"ดีมาก"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"คุณทำท่าทางสัมผัสเพื่อย้อนกลับสำเร็จแล้ว"</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"หากต้องการย้อนกลับโดยใช้ทัชแพด ให้ใช้ 3 นิ้วปัดไปทางซ้ายหรือขวา"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ไปที่หน้าแรก"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"ใช้ 3 นิ้วปัดขึ้นบนทัชแพด"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"เก่งมาก"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"คุณทำท่าทางสัมผัสเพื่อไปที่หน้าแรกสำเร็จแล้ว"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"ใช้ 3 นิ้วปัดขึ้นบนทัชแพดเพื่อไปยังหน้าจอหลัก"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"ดูแอปล่าสุด"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"เยี่ยมมาก"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"คุณทำท่าทางสัมผัสเพื่อดูแอปล่าสุดสำเร็จแล้ว"</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"หากต้องการดูแอปล่าสุด ให้ใช้ 3 นิ้วปัดขึ้นแล้วค้างไว้บนทัชแพด"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"ดูแอปทั้งหมด"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"กดปุ่มดำเนินการบนแป้นพิมพ์"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"ยอดเยี่ยม"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"คุณทำท่าทางสัมผัสเพื่อดูแอปทั้งหมดสำเร็จแล้ว"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"กดปุ่มดำเนินการบนแป้นพิมพ์เพื่อดูแอปทั้งหมด"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ภาพเคลื่อนไหวของบทแนะนำ คลิกเพื่อหยุดชั่วคราวและเล่นต่อ"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"ไฟแบ็กไลต์ของแป้นพิมพ์"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"ระดับที่ %1$d จาก %2$d"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ee15260..c47da32 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Mga emergency na tawag o SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"walang signal"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"isang bar"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"dalawang bar"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"tatlong bar"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"apat na bar"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"puno ang signal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Makikita sa itaas ng mga notification ng pag-uusap at bilang larawan sa profile sa lock screen, lumalabas bilang bubble, naaabala ang Huwag Istorbohin"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Priyoridad"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"Hindi sinusuportahan ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang mga feature ng pag-uusap"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Magbigay ng Feedback sa Bundle"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Hindi puwedeng baguhin ang mga notification na ito."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Hindi mabago ang mga notification ng tawag."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Hindi mako-configure dito ang pangkat na ito ng mga notification"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"I-lock ang screen"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Magtala"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Pag-multitask"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Gumamit ng split screen nang nasa kanan ang app"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Gumamit ng split screen nang nasa kaliwa ang app"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Lumipat sa full screen"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Lumipat sa app sa kanan o ibaba habang ginagamit ang split screen"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Lumipat sa app sa kaliwa o itaas habang ginagamit ang split screen"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Habang nasa split screen: magpalit-palit ng app"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Power menu"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> ng <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Lock screen"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Puwede mong hanapin ang teleponong ito gamit ang Hanapin ang Aking Device kahit kapag naka-off ito"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Nagsa-shut down…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Tingnan ang mga hakbang sa pangangalaga"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Tingnan ang mga hakbang sa pangangalaga"</string>
@@ -1466,22 +1468,27 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Pumunta sa home"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Tingnan ang mga kamakailang app"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tapos na"</string>
+    <string name="gesture_error_title" msgid="469064941635578511">"Subukan ulit!"</string>
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Bumalik"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Mag-swipe pakaliwa o pakanan gamit ang tatlong daliri sa iyong touchpad"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Magaling!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Nakumpleto mo na ang galaw para bumalik."</string>
+    <string name="touchpad_back_gesture_error_body" msgid="7112668207481458792">"Para bumalik gamit ang iyong touchpad, mag-swipe pakaliwa o pakanan gamit ang tatlong daliri"</string>
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Pumunta sa home"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Mag-swipe pataas gamit ang tatlong daliri sa iyong touchpad"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Magaling!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Nakumpleto mo na ang galaw para pumunta sa home"</string>
+    <string name="touchpad_home_gesture_error_body" msgid="3810674109999513073">"Mag-swipe pataas gamit ang tatlong daliri sa iyong touchpad para pumunta sa home screen mo"</string>
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Tingnan ang mga kamakailang app"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Mag-swipe pataas at i-hold gamit ang tatlong daliri sa iyong touchpad"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Magaling!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Nakumpleto mo ang galaw sa pag-view ng mga kamakailang app."</string>
+    <string name="touchpad_recent_gesture_error_body" msgid="8695535720378462022">"Para tingnan ang mga kamakailang app, mag-swipe pataas at i-hold gamit ang tatlong daliri sa iyong touchpad"</string>
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Tingnan ang lahat ng app"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Pindutin ang action key sa iyong keyboard"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Magaling!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Nakumpleto mo ang galaw sa pag-view ng lahat ng app"</string>
+    <string name="touchpad_action_key_error_body" msgid="8685502040091860903">"Pindutin ang action key sa iyong keyboard para tingnan ang lahat ng app mo"</string>
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Animation ng tutorial, i-click para i-pause at ipagpatuloy ang paglalaro."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Backlight ng keyboard"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Level %1$d sa %2$d"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c12f7b6..2a3c4426 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Widget\'lar"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"\"Widget\'lar\" kısayolunu eklemek için ayarlarda \"Widget\'ları kilit ekranında göster\" seçeneğinin etkinleştirildiğinden emin olun."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Ayarlar"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran koruyucuyu göster düğmesi"</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Bildirimler"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Görüşmeler"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sessiz bildirimlerin tümünü temizle"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Bildirim ayarlarını aç"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Bildirimler, Rahatsız Etmeyin özelliği tarafından duraklatıldı"</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Bildirim yok}=1{Bildirimler {mode} tarafından duraklatıldı}=2{Bildirimler, {mode} ve bir diğer mod tarafından duraklatıldı}other{Bildirimler, {mode} ve # diğer mod tarafından duraklatıldı}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Şimdi başlat"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Acil Uydu Bağlantısı"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Acil durum aramaları veya acil yardım"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"sinyal yok"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"tek çubuk"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">",ki çubuk"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"üç çubuk"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"dört çubuk"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"tam sinyal"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Görüşme bildirimlerinin üstünde ve kilit ekranında profil resmi olarak gösterilir, baloncuk olarak görünür, Rahatsız Etmeyin\'i kesintiye uğratır"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Öncelikli"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>, sohbet özelliklerini desteklemiyor"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Paketle İlgili Geri Bildirim Verin"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirimler değiştirilemez."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Arama bildirimleri değiştirilemez."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Bu bildirim grubu burada yapılandırılamaz"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Kilit ekranı"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Not al"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Çoklu görev"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Sağdaki uygulamayla birlikte bölünmüş ekranı kullan"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Soldaki uygulamayla birlikte bölünmüş ekranı kullan"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Tam ekran moduna geç"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Bölünmüş ekran kullanırken sağdaki veya alttaki uygulamaya geçiş yap"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Bölünmüş ekran kullanırken soldaki veya üstteki uygulamaya geçiş yapın"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Bölünmüş ekran etkinken: Bir uygulamayı başkasıyla değiştir"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Güç menüsü"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Kilit ekranı"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Bu telefonu kapalıyken bile Cihazımı Bul işleviyle bulabilirsiniz."</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Kapanıyor…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Bakımla ilgili adımlara bakın"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bakımla ilgili adımlara bakın"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Ana sayfaya git"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Son uygulamaları görüntüle"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Bitti"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Geri dön"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Dokunmatik alanda üç parmağınızla sola veya sağa kaydırın"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Güzel!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Geri dön hareketini tamamladınız."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Ana sayfaya gidin"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Dokunmatik alanda üç parmağınızla yukarı kaydırın"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Tebrikler!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ana ekrana git hareketini tamamladınız"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Son uygulamaları görüntüle"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Dokunmatik alanda üç parmağınızla yukarı doğru kaydırıp basılı tutun"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Tebrikler!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Son uygulamaları görüntüleme hareketini tamamladınız."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Tüm uygulamaları göster"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klavyenizde eylem tuşuna basın"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Tebrikler!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Tüm uygulamaları görüntüleme hareketini tamamladınız"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Eğitim animasyonu, oynatmayı duraklatmak ve sürdürmek için tıklayın."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klavye aydınlatması"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Seviye %1$d / %2$d"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index c2c3c61..68129a8 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Віджети"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Щоб додати ярлик \"Віджети\", переконайтеся, що в налаштуваннях увімкнено опцію \"Показувати віджети на заблокованому екрані\"."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Налаштування"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Кнопка \"Показати заставку\""</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Сповіщення"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Розмови"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Очистити всі беззвучні сповіщення"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Відкрити налаштування сповіщень"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Режим \"Не турбувати\" призупинив сповіщення"</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Немає сповіщень}=1{Режим \"{mode}\" призупинив надсилання сповіщень}=2{\"{mode}\" і ще один режим призупинили надсилання сповіщень}one{\"{mode}\" і ще # режим призупинили надсилання сповіщень}few{\"{mode}\" і ще # режими призупинили надсилання сповіщень}many{\"{mode}\" і ще # режимів призупинили надсилання сповіщень}other{\"{mode}\" і ще # режиму призупинили надсилання сповіщень}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Почати зараз"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Супутниковий сигнал SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Екстрені виклики або сигнал SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"немає сигналу"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"одна смужка сигналу"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"дві смужки сигналу"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"три смужки сигналу"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"чотири смужки сигналу"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"максимальний сигнал"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"З’являється вгорі сповіщень про розмови і як зображення профілю на заблокованому екрані, відображається як спливаючий чат, перериває режим \"Не турбувати\""</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Пріоритет"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не підтримує функції розмов"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Надіслати груповий відгук"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Ці сповіщення не можна змінити."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Сповіщення про виклик не можна змінити."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Цю групу сповіщень не можна налаштувати тут"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Заблокувати екран"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Створити нотатку"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Багатозадачність"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Розділити екран і показувати додаток праворуч"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Розділити екран і показувати додаток ліворуч"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Перейти в повноекранний режим"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Перейти до додатка праворуч або внизу на розділеному екрані"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Під час розділення екрана перемикатися на додаток ліворуч або вгорі"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Під час розділення екрана: замінити додаток іншим"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки живлення"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокований екран"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Ви зможете визначити місцеположення цього телефона, навіть коли його вимкнено, за допомогою сервісу Знайти пристрій"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Вимкнення…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Переглянути запобіжні заходи"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Переглянути запобіжні заходи"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Перейти на головний екран"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Переглянути нещодавні додатки"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Готово"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Назад"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Проведіть трьома пальцями вліво чи вправо по сенсорній панелі"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Чудово!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ви виконали жест \"Назад\"."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Перейти на головний екран"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Проведіть трьома пальцями вгору на сенсорній панелі"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Чудово!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ви виконали жест переходу на головний екран"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Переглянути нещодавні додатки"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Проведіть трьома пальцями вгору й утримуйте їх на сенсорній панелі"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Чудово!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Ви виконали жест для перегляду нещодавно відкритих додатків."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Переглянути всі додатки"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Натисніть клавішу дії на клавіатурі"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Чудово!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Ви виконали жест для перегляду всіх додатків"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Навчальна анімація. Натисніть, щоб призупинити або відновити відтворення."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Підсвічування клавіатури"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Рівень %1$d з %2$d"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 8b3b9a0..63213da 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"‏سیٹلائٹ SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"‏ایمرجنسی کالز یا SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>، <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>۔"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"کوئی سگنل نہیں"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ایک بار"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"دو بارز"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"تین بارز"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"چار بارز"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"سگنل فل ہے"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"یہ گفتگو کی اطلاعات کے اوپری حصّے پر اور مقفل اسکرین پر پروفائل کی تصویر کے بطور دکھائی دیتا ہے، بلبلے کے بطور ظاہر ہوتا ہے، \'ڈسٹرب نہ کریں\' میں مداخلت کرتا ہے"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"ترجیح"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ایپ گفتگو کی خصوصیات کو سپورٹ نہیں کرتی ہے"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"بنڈل کے تاثرات فراہم کریں"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"ان اطلاعات کی ترمیم نہیں کی جا سکتی۔"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"کال کی اطلاعات میں ترمیم نہیں کی جا سکتی۔"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"اطلاعات کے اس گروپ کو یہاں کنفیگر نہیں کیا جا سکتا"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"اسکرین لاک کریں"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"نوٹ لیں"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"ملٹی ٹاسکنگ"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"بائیں جانب ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"دائیں جانب ایپ کے ساتھ اسپلٹ اسکرین کا استعمال کریں"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"فُل اسکرین پر سوئچ کریں"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"اسپلٹ اسکرین کا استعمال کرتے ہوئے دائیں یا نیچے ایپ پر سوئچ کریں"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"اسپلٹ اسکرین کا استعمال کرتے ہوئے بائیں یا اوپر ایپ پر سوئچ کریں"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"اسپلٹ اسکرین کے دوران: ایک ایپ کو دوسرے سے تبدیل کریں"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"پاور مینیو"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"مقفل اسکرین"</string>
-    <string name="finder_active" msgid="7907846989716941952">"پاور آف ہونے پر بھی آپ میرا آلہ ڈھونڈیں کے ساتھ اس فون کو تلاش کر سکتے ہیں"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"بند ہو رہا ہے…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"نگہداشت کے اقدامات ملاحظہ کریں"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"نگہداشت کے اقدامات ملاحظہ کریں"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"ہوم پر جائیں"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"حالیہ ایپس دیکھیں"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"ہو گیا"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"واپس جائیں"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"اپنے ٹچ پیڈ پر تین انگلیوں کا استعمال کرتے ہوئے دائیں یا بائیں طرف سوائپ کریں"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"عمدہ!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"آپ نے واپس جائیں اشارے کو مکمل کر لیا۔"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"ہوم پر جائیں"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"اپنے ٹچ پیڈ پر تین انگلیوں کی مدد سے اوپر کی طرف سوائپ کریں"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"بہترین!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"آپ نے ہوم پر جانے کا اشارہ مکمل کر لیا"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"حالیہ ایپس دیکھیں"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"اپنے ٹچ پیڈ پر تین انگلیوں کا استعمال کرتے ہوئے اوپر کی طرف سوائپ کریں اور دبائے رکھیں"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"بہترین!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"آپ نے حالیہ ایپس دیکھیں کا اشارہ مکمل کر لیا ہے۔"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"سبھی ایپس دیکھیں"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"اپنے کی بورڈ پر ایکشن کلید دبائیں"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"بہت خوب!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"آپ نے سبھی ایپس دیکھیں کا اشارہ مکمل کر لیا ہے"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"ٹیوٹوریل اینیمیشن، روکنے کے لیے کلک کریں اور چلانا دوبارہ شروع کریں۔"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"کی بورڈ بیک لائٹ"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"‏%2$d میں سے ‎%1$d کا لیول"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index dc01a49..488852f5 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Vidjetlar"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"“Vidjetlar” yorligʻini qoʻshish uchun sozlamalarda “Vidjetlarni ekran qulfida chiqarish” yoqilganini tekshiring."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Sozlamalar"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Ekran lavhasi tugmasini chiqarish"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Sputnik SOS"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Favqulodda chaqiruvlar yoki SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"signal yoʻq"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"bitta ustun"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"ikkita ustun"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"uchta ustun"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"toʻrtta ustun"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"signal toʻliq"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Suhbat bildirishnomalari tepasida va ekran qulfida profil rasmi sifatida chiqariladi, bulutcha sifatida chiqadi, Bezovta qilinmasin rejimini bekor qiladi"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Muhim"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasida suhbat funksiyalari ishlamaydi"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Jamlanma fikr-mulohaza bildirish"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirishnomalarni tahrirlash imkonsiz."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Chaqiruv bildirishnomalarini tahrirlash imkonsiz."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Ushbu bildirishnomalar guruhi bu yerda sozlanmaydi"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Ekran qulfi"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Qayd yaratish"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multi-vazifalilik"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Ekranni ajratib, joriy ilovani oʻngga joylash"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Ekranni ajratib, joriy ilovani chapga joylash"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Butun ekran rejimiga kirish"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Ajratilgan ekranda oʻngdagi yoki pastdagi ilovaga almashish"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Ajratilgan ekranda chapdagi yoki yuqoridagi ilovaga almashish"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ajratilgan rejimda ilovalarni oʻzaro almashtirish"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Quvvat menyusi"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran qulfi"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Oʻchiq boʻlsa ham “Qurilmani top” funksiyasi yordamida bu telefonni topish mumkin"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Oʻchirilmoqda…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Batafsil axborot"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Batafsil axborot"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Boshiga qaytish"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Oxirgi ilovalarni koʻrish"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Tayyor"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Orqaga qaytish"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Sensorli panelda uchta barmoq bilan chapga yoki oʻngga suring"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Yaxshi!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ortga qaytish ishorasi darsini tamomladingiz."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Boshiga qaytish"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Sensorli panelda uchta barmoq bilan tepaga suring"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Barakalla!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Bosh ekranni ochish ishorasi darsini tamomladingiz"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Oxirgi ilovalarni koʻrish"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Sensorli panelda uchta barmoq bilan tepaga surib, bosib turing"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Barakalla!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Oxirgi ilovalarni koʻrish ishorasini tugalladingiz."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Barcha ilovalarni koʻrish"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Klaviaturadagi amal tugmasini bosing"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Barakalla!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Hamma ilovalarni koʻrish ishorasini tugalladingiz"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Qoʻllanma animatsiyasi, pauza qilish va ijroni davom ettirish uchun bosing."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Klaviatura orqa yoritkichi"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Daraja: %1$d / %2$d"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 1dd6042..1b505d3d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Tiện ích"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Để thêm phím tắt \"Tiện ích\", hãy nhớ bật tuỳ chọn \"Hiện tiện ích trên màn hình khoá\" trong phần cài đặt."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Cài đặt"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Hiện nút trình bảo vệ màn hình"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Liên lạc khẩn cấp qua vệ tinh"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Cuộc gọi khẩn cấp hoặc SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"không có tín hiệu"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"1 vạch"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"2 vạch"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"3 vạch"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"4 vạch"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"tín hiệu đầy đủ"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Hiện ở đầu phần thông báo cuộc trò chuyện và ở dạng ảnh hồ sơ trên màn hình khóa, xuất hiện ở dạng bong bóng, làm gián đoạn chế độ Không làm phiền"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> không hỗ trợ các tính năng trò chuyện"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Phản hồi về gói"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Không thể sửa đổi các thông báo này."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Không thể sửa đổi các thông báo cuộc gọi."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Không thể định cấu hình nhóm thông báo này tại đây"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Màn hình khoá"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Tạo ghi chú"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Đa nhiệm"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Dùng tính năng chia đôi màn hình với ứng dụng ở bên phải"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Dùng tính năng chia đôi màn hình với ứng dụng ở bên trái"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Chuyển sang chế độ toàn màn hình"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Chuyển sang ứng dụng bên phải hoặc ở dưới khi đang chia đôi màn hình"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Chuyển sang ứng dụng bên trái hoặc ở trên khi đang chia đôi màn hình"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Trong chế độ chia đôi màn hình: thay một ứng dụng bằng ứng dụng khác"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Trình đơn nguồn"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Màn hình khóa"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Bạn có thể định vị chiếc điện thoại này bằng ứng dụng Tìm thiết bị của tôi ngay cả khi điện thoại tắt nguồn"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Đang tắt…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Xem các bước chăm sóc"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Xem các bước chăm sóc"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Chuyển đến màn hình chính"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Xem các ứng dụng gần đây"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Xong"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Quay lại"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Dùng 3 ngón tay vuốt sang trái hoặc sang phải trên bàn di chuột"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Tuyệt vời!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Bạn đã thực hiện xong cử chỉ quay lại."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Chuyển đến màn hình chính"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Dùng 3 ngón tay vuốt lên trên bàn di chuột"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Tuyệt vời!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Bạn đã thực hiện xong cử chỉ chuyển đến màn hình chính"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Xem các ứng dụng gần đây"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Dùng 3 ngón tay vuốt lên và giữ trên bàn di chuột"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Tuyệt vời!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Bạn đã hoàn tất cử chỉ xem ứng dụng gần đây."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Xem tất cả các ứng dụng"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Nhấn phím hành động trên bàn phím"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Rất tốt!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Bạn đã hoàn tất cử chỉ xem tất cả các ứng dụng"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Ảnh động trong phần hướng dẫn, nhấp để tạm dừng và tiếp tục phát."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Đèn nền bàn phím"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Độ sáng %1$d/%2$d"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e18fcec..8d6ec77 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"卫星紧急呼救"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"紧急呼叫或紧急求救"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>,<xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>。"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"无信号"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"信号强度为一格"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"信号强度为两格"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"信号强度为三格"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"信号强度为四格"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"信号满格"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以气泡形式显示在对话通知顶部(屏幕锁定时显示为个人资料照片),并且会中断勿扰模式"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"优先"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>不支持对话功能"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"提供有关套装的反馈"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"无法修改这些通知。"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"无法修改来电通知。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"您无法在此处配置这组通知"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"锁定屏幕"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"添加记事"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多任务处理"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"使用分屏模式,并将应用置于右侧"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"使用分屏模式,并将应用置于左侧"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"切换到全屏模式"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分屏模式时,切换到右侧或下方的应用"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分屏模式时,切换到左侧或上方的应用"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"在分屏期间:将一个应用替换为另一个应用"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"电源菜单"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"锁定屏幕"</string>
-    <string name="finder_active" msgid="7907846989716941952">"即使手机已关机,您也可以通过“查找我的设备”找到这部手机"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"正在关机…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看处理步骤"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看处理步骤"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"前往主屏幕"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近用过的应用"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"在触控板上用三根手指向左或向右滑动"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"太棒了!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"您已完成“返回”手势教程。"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"前往主屏幕"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"在触控板上用三根手指向上滑动"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"太棒了!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"您已完成“前往主屏幕”手势"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近用过的应用"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"在触控板上用三根手指向上滑动并按住"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"太棒了!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"您已完成“查看最近用过的应用”的手势教程。"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有应用"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按键盘上的快捷操作按键"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"非常棒!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"您已完成“查看所有应用”手势教程"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"教程动画,点击可暂停和继续播放。"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"键盘背光"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 级,共 %2$d 级"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 871bd31..b1df372 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -753,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連接"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或 SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>,<xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>。"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"無訊號"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"一格"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"兩格"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"三格"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"四格"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"訊號滿格"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
@@ -786,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話氣泡形式顯示在對話通知頂部 (在上鎖畫面會顯示為個人檔案相片),並會中斷「請勿打擾」模式"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"提供套裝意見"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改通話通知。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在此設定這組通知"</string>
@@ -872,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"上鎖畫面"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"寫筆記"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"使用分割螢幕,並在右側顯示應用程式"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"使用分割螢幕,並在左側顯示應用程式"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"切換至全螢幕"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割螢幕時,切換至右邊或下方的應用程式"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割螢幕時,切換至左邊或上方的應用程式"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"使用分割螢幕期間:更換應用程式"</string>
@@ -979,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源選單"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string>
-    <string name="finder_active" msgid="7907846989716941952">"即使手機關機,仍可透過「尋找我的裝置」尋找此手機"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"正在關機…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看保養步驟"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看保養步驟"</string>
@@ -1466,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"返回主畫面"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近使用的應用程式"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"在觸控板上用三隻手指向左或向右滑動"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"很好!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"你已完成「返回」手勢的教學課程。"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"在觸控板上用三隻手指向上滑動"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"太好了!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"你已完成「返回主畫面」手勢的教學課程"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近使用的應用程式"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"在觸控板上用三隻手指向上滑動並按住"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"做得好!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢的教學課程。"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有應用程式"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按下鍵盤上的快捷操作鍵"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"做得好!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"你已完成「查看所有應用程式」手勢的教學課程"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"教學動畫,按一下以暫停和繼續播放。"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 33411754..373f1af 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"小工具"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"如要新增「小工具」捷徑,請務必前往設定啟用「在螢幕鎖定畫面上顯示小工具」。"</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"設定"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"顯示螢幕保護程式按鈕"</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>
@@ -754,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連線"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或緊急求救"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>,<xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>。"</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"沒有訊號"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"訊號強度一格"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"訊號強度兩格"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"訊號強度三格"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"訊號強度四格"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"訊號滿格"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
@@ -787,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"以對話框的形式顯示在對話通知頂端 (螢幕鎖定時會顯示為個人資料相片),並會中斷「零打擾」模式"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"提供套裝組合意見"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"無法修改這些通知。"</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"無法修改來電通知。"</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"無法在這裡設定這個通知群組"</string>
@@ -873,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"螢幕鎖定"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"新增記事"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"多工處理"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"使用分割畫面,並在右側顯示應用程式"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"使用分割畫面,並在左側顯示應用程式"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"切換至全螢幕模式"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"使用分割畫面時,切換到右邊或上方的應用程式"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"使用分割畫面時,切換到左邊或上方的應用程式"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"使用分割畫面期間:更換應用程式"</string>
@@ -980,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string>
-    <string name="finder_active" msgid="7907846989716941952">"即使這支手機關機,仍可透過「尋找我的裝置」找出手機位置"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"關機中…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"查看處理步驟"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看處理步驟"</string>
@@ -1467,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"返回主畫面"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"查看最近使用的應用程式"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"完成"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"返回"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"在觸控板上用三指向左或向右滑動"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"很好!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"你已完成「返回」手勢的教學課程。"</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"返回主畫面"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"在觸控板上用三指向上滑動"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"太棒了!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"你已完成「返回主畫面」手勢教學課程"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"查看最近使用的應用程式"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"在觸控板上用三指向上滑動並按住"</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"太棒了!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"你已完成「查看最近使用的應用程式」手勢教學課程。"</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"查看所有應用程式"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"按下鍵盤上的快捷操作鍵"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"非常好!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"你已完成「查看所有應用程式」手勢教學課程"</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"教學課程動畫,按一下即可暫停和繼續播放。"</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"鍵盤背光"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"第 %1$d 級,共 %2$d 級"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a9fa1ba..a18d9e7 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -531,8 +531,7 @@
     <string name="glanceable_hub_lockscreen_affordance_label" msgid="1461611028615752141">"Amawijethi"</string>
     <string name="glanceable_hub_lockscreen_affordance_disabled_text" msgid="599170482297578735">"Ukuze ufake isinqamuleli esithi \"Amawijethi\", qinisekisa ukuthi okuthi \"Bonisa amawijethi esikrinini sokukhiya\" kunikwe amandla kumasethingi."</string>
     <string name="glanceable_hub_lockscreen_affordance_action_button_label" msgid="7636151133344609375">"Amasethingi"</string>
-    <!-- no translation found for accessibility_glanceable_hub_to_dream_button (7552776300297055307) -->
-    <skip />
+    <string name="accessibility_glanceable_hub_to_dream_button" msgid="7552776300297055307">"Bonisa inkinobho yesigcini sesikrini"</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>
@@ -593,8 +592,7 @@
     <string name="notification_section_header_alerting" msgid="5581175033680477651">"Izaziso"</string>
     <string name="notification_section_header_conversations" msgid="821834744538345661">"Izingxoxo"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Sula zonke izaziso ezithulile"</string>
-    <!-- no translation found for accessibility_notification_section_header_open_settings (6235202417954844004) -->
-    <skip />
+    <string name="accessibility_notification_section_header_open_settings" msgid="6235202417954844004">"Vula amasethingi ezaziso"</string>
     <string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Izaziso zimiswe okwesikhashana ukungaphazamisi"</string>
     <string name="modes_suppressing_shade_text" msgid="6037581130837903239">"{count,plural,offset:1 =0{Azikho izaziso}=1{Izaziso zimiswe okwesikhashana yi-{mode}}=2{Izaziso zimiswe okwesikhashana yi-{mode} nelinye imodi elilodwa}one{Izaziso zimiswe okwesikhashana yi-{mode} kanye namanye amamodi angu-#}other{Izaziso zimiswe okwesikhashana yi-{mode} kanye namanye amamodi angu-#}}"</string>
     <string name="media_projection_action_text" msgid="3634906766918186440">"Qala manje"</string>
@@ -755,6 +753,13 @@
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
     <string name="satellite_connected_carrier_text" msgid="118524195198532589">"Isethelayithi yokuxhumana ngezimo eziphuthumayo"</string>
     <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ikholi ephuthumayo noma i-SOS"</string>
+    <string name="accessibility_phone_string_format" msgid="7798841417881811812">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="SIGNAL_STRENGTH_DESCRIPTION">%2$s</xliff:g>."</string>
+    <string name="accessibility_no_signal" msgid="7052827511409250167">"ayikho isignali"</string>
+    <string name="accessibility_one_bar" msgid="5342012847647834506">"ibha eyodwa"</string>
+    <string name="accessibility_two_bars" msgid="122628483354508429">"amabha amabili"</string>
+    <string name="accessibility_three_bars" msgid="5143286602926069024">"amabha amathathu"</string>
+    <string name="accessibility_four_bars" msgid="8838495563822541844">"amabha amane"</string>
+    <string name="accessibility_signal_full" msgid="1519655809806462972">"isignali egcwele"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
@@ -788,7 +793,6 @@
     <string name="notification_channel_summary_priority_all" msgid="7151752959650048285">"Ivela phezu kwezaziso zengxoxo futhi njengesithombe sephrofayela esikrinini sokukhiya, ivela njengebhamuza, ukuphazamisa okuthi Ungaphazamisi"</string>
     <string name="notification_priority_title" msgid="2079708866333537093">"Okubalulekile"</string>
     <string name="no_shortcut" msgid="8257177117568230126">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayisekeli izici zengxoxo"</string>
-    <string name="notification_guts_bundle_feedback" msgid="5393570876655201459">"Nikeza Impendulo Yenqwaba"</string>
     <string name="notification_unblockable_desc" msgid="2073030886006190804">"Lezi zaziso azikwazi ukushintshwa."</string>
     <string name="notification_unblockable_call_desc" msgid="5907328164696532169">"Izaziso zekholi azikwazi ukushintshwa."</string>
     <string name="notification_multichannel_desc" msgid="7414593090056236179">"Leli qembu lezaziso alikwazi ukulungiselelwa lapha"</string>
@@ -874,12 +878,9 @@
     <string name="group_system_lock_screen" msgid="7391191300363416543">"Khiya isikrini"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Thatha inothi"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Ukwenza imisebenzi eminingi"</string>
-    <!-- no translation found for system_multitasking_rhs (8779289852395243004) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (7348595296208696452) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (4940465971687159429) -->
-    <skip />
+    <string name="system_multitasking_rhs" msgid="8779289852395243004">"Sebenzisa ukuhlukanisa isikrini nge-app kwesokudla"</string>
+    <string name="system_multitasking_lhs" msgid="7348595296208696452">"Sebenzisa ukuhlukanisa isikrini nge-app kwesokunxele"</string>
+    <string name="system_multitasking_full_screen" msgid="4940465971687159429">"Shintshela esikrinini esigcwele"</string>
     <string name="system_multitasking_splitscreen_focus_rhs" msgid="3838578650313318508">"Shintshela ku-app ngakwesokudla noma ngezansi ngenkathi usebenzisa uhlukanisa isikrini"</string>
     <string name="system_multitasking_splitscreen_focus_lhs" msgid="3164261844398662518">"Shintshela ku-app ngakwesokunxele noma ngaphezulu ngenkathi usebenzisa ukuhlukanisa isikrini"</string>
     <string name="system_multitasking_replace" msgid="7410071959803642125">"Ngesikhathi sokuhlukaniswa kwesikrini: shintsha i-app ngenye"</string>
@@ -981,7 +982,6 @@
     <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Imenyu yamandla"</string>
     <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string>
     <string name="tuner_lock_screen" msgid="2267383813241144544">"Khiya isikrini"</string>
-    <string name="finder_active" msgid="7907846989716941952">"Ungabeka le foni ngokuthi Thola Ifoni Yami ngisho noma ivaliwe"</string>
     <string name="shutdown_progress" msgid="5464239146561542178">"Iyacisha…"</string>
     <string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Bona izinyathelo zokunakekelwa"</string>
     <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bona izinyathelo zokunakekelwa"</string>
@@ -1468,22 +1468,32 @@
     <string name="touchpad_tutorial_home_gesture_button" msgid="8023973153559885624">"Iya ekhasini lokuqala"</string>
     <string name="touchpad_tutorial_recent_apps_gesture_button" msgid="8919227647650347359">"Buka ama-app akamuva"</string>
     <string name="touchpad_tutorial_done_button" msgid="176168488821755503">"Kwenziwe"</string>
+    <!-- no translation found for gesture_error_title (469064941635578511) -->
+    <skip />
     <string name="touchpad_back_gesture_action_title" msgid="7199067250654332735">"Buyela emuva"</string>
     <string name="touchpad_back_gesture_guidance" msgid="5352221087725906542">"Swayiphela kwesokunxele noma kwesokudla usebenzisa iminwe emithathu kuphedi yokuthinta"</string>
     <string name="touchpad_back_gesture_success_title" msgid="7370719098633023496">"Kuhle!"</string>
     <string name="touchpad_back_gesture_success_body" msgid="2324724953720741719">"Ukuqedile ukuthinta kokubuyela emuva."</string>
+    <!-- no translation found for touchpad_back_gesture_error_body (7112668207481458792) -->
+    <skip />
     <string name="touchpad_home_gesture_action_title" msgid="8885107349719257882">"Iya ekhasini lokuqala"</string>
     <string name="touchpad_home_gesture_guidance" msgid="4178219118381915899">"Swayiphela phezulu ngeminwe emithathu ephedini yakho yokuthinta"</string>
     <string name="touchpad_home_gesture_success_title" msgid="3648264553645798470">"Umsebenzi omuhle!"</string>
     <string name="touchpad_home_gesture_success_body" msgid="2590690589194027059">"Ukuqedile ukunyakaza kokuya ekhaya"</string>
+    <!-- no translation found for touchpad_home_gesture_error_body (3810674109999513073) -->
+    <skip />
     <string name="touchpad_recent_apps_gesture_action_title" msgid="934906836867137906">"Buka ama-app akamuva"</string>
     <string name="touchpad_recent_apps_gesture_guidance" msgid="6304446013842271822">"Swayiphela phezulu bese ubamba usebenzisa iminwe emithathu ephedini yokuthinta."</string>
     <string name="touchpad_recent_apps_gesture_success_title" msgid="8481920554139332593">"Umsebenzi omuhle!"</string>
     <string name="touchpad_recent_apps_gesture_success_body" msgid="4334263906697493273">"Uqedele ukubuka ukuthinta kwama-app akamuva."</string>
+    <!-- no translation found for touchpad_recent_gesture_error_body (8695535720378462022) -->
+    <skip />
     <string name="tutorial_action_key_title" msgid="8172535792469008169">"Buka wonke ama-app"</string>
     <string name="tutorial_action_key_guidance" msgid="5040613427202799294">"Cindezela inkinobho yokufinyelela kukhibhodi yakho"</string>
     <string name="tutorial_action_key_success_title" msgid="2371827347071979571">"Wenze kahle!"</string>
     <string name="tutorial_action_key_success_body" msgid="1688986269491357832">"Uqedele ukunyakazisa kokubuka onke ama-app."</string>
+    <!-- no translation found for touchpad_action_key_error_body (8685502040091860903) -->
+    <skip />
     <string name="tutorial_animation_content_description" msgid="2698816574982370184">"Okopopayi okokufundisa, chofoza ukuze umise kancane futhi uqalise kabusha ukudlala."</string>
     <string name="keyboard_backlight_dialog_title" msgid="8273102932345564724">"Ilambu lekhibhodi"</string>
     <string name="keyboard_backlight_value" msgid="7336398765584393538">"Ileveli %1$d ka-%2$d"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 28df2e2..d2b7d0b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,6 +31,9 @@
     <!-- The dark background color behind the shade -->
     <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_light</color>
 
+    <!-- Colors for notification shade/scrim -->
+    <color name="shade_panel">@android:color/system_accent1_800</color>
+
     <!-- The color of the background in the separated list of the Global Actions menu -->
     <color name="global_actions_separated_background">#F5F5F5</color>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 113f3d2..940e87d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -1103,4 +1103,8 @@
     Whether the user switching can only happen by logging out and going through the system user (login screen).
     -->
     <bool name="config_userSwitchingMustGoThroughLoginScreen">false</bool>
+
+
+    <!-- The dream component used when the device is low light environment. -->
+    <string translatable="false" name="config_lowLightDreamComponent"/>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 35cfd08..6994a55 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -782,6 +782,13 @@
     <!-- The top margin for the notification children container in its non-expanded form. -->
     <dimen name="notification_children_container_margin_top">48dp</dimen>
 
+    <!-- The spacing between the notification children container in its non-expanded form, and the
+         header text above it, scaling with text size. This value is chosen so that, taking into
+         account the text spacing for both the text in the top line and the text in the container,
+         the distance between them is 4dp with the default screen configuration (and will grow
+         accordingly for larger font sizes). -->
+    <dimen name="notification_2025_children_container_margin_top">@*android:dimen/notification_2025_content_margin_top</dimen>
+
     <!-- The height of the gap between adjacent notification sections. -->
     <dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
 
@@ -1488,7 +1495,7 @@
     <dimen name="screenrecord_spinner_height">72dp</dimen>
     <dimen name="screenrecord_spinner_margin">24dp</dimen>
     <dimen name="screenrecord_spinner_text_padding_start">20dp</dimen>
-    <dimen name="screenrecord_spinner_text_padding_end">80dp</dimen>
+    <dimen name="screenrecord_spinner_text_padding_end">20dp</dimen>
     <dimen name="screenrecord_spinner_arrow_size">24dp</dimen>
     <dimen name="screenrecord_spinner_background_radius">28dp</dimen>
 
@@ -1514,7 +1521,6 @@
     <dimen name="media_output_dialog_header_icon_padding">16dp</dimen>
     <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
     <dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
-    <dimen name="media_output_dialog_app_tier_icon_size">20dp</dimen>
     <dimen name="media_output_dialog_background_radius">16dp</dimen>
     <dimen name="media_output_dialog_active_background_radius">30dp</dimen>
     <dimen name="media_output_dialog_default_margin_end">16dp</dimen>
@@ -2106,6 +2112,8 @@
 
     <fraction name="volume_dialog_half_opened_bias">0.2</fraction>
 
+    <dimen name="volume_dialog_slider_max_deviation">56dp</dimen>
+
     <dimen name="volume_dialog_background_square_corner_radius">12dp</dimen>
 
     <dimen name="volume_dialog_ringer_drawer_button_size">@dimen/volume_dialog_button_size</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 56aaf4c..cd37c22 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -289,8 +289,9 @@
     <!-- Screen recording permission option for recording just a single app [CHAR LIMIT=50] -->
     <string name="screenrecord_permission_dialog_option_text_single_app">Record one app</string>
     <!-- Screen recording permission option for recording the whole screen [CHAR LIMIT=50] -->
-    <string name="screenrecord_permission_dialog_option_text_entire_screen" >Record entire screen</string>
-    <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display">Record entire screen: %s</string>
+    <string name="screenrecord_permission_dialog_option_text_entire_screen" >Record this screen</string>
+    <!-- Screen recording permission option for recording a connected external display. %s will be replaced by the display name [CHAR LIMIT=50] -->
+    <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display">Record %s</string>
     <!-- Message reminding the user that sensitive information may be captured during a full screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
     <string name="screenrecord_permission_dialog_warning_entire_screen">When you’re recording your entire screen, anything shown on your screen is recorded. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
     <!-- Message reminding the user that sensitive information may be captured during a single app screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
@@ -1004,6 +1005,20 @@
     <string name="hearing_devices_preset_label">Preset</string>
     <!-- QuickSettings: Content description for the icon that indicates the item is selected [CHAR LIMIT=NONE]-->
     <string name="hearing_devices_spinner_item_selected">Selected</string>
+    <!-- QuickSettings: Title for ambient controls. [CHAR LIMIT=40]-->
+    <string name="hearing_devices_ambient_label">Surroundings</string>
+    <!-- QuickSettings: The text to show the control is for left side device. [CHAR LIMIT=30] -->
+    <string name="hearing_devices_ambient_control_left">Left</string>
+    <!-- QuickSettings: The text to show the control is for right side device. [CHAR LIMIT=30] -->
+    <string name="hearing_devices_ambient_control_right">Right</string>
+    <!-- QuickSettings: Content description for a button, that expands ambient volume sliders [CHAR_LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_expand_controls">Expand to left and right separated controls</string>
+    <!-- QuickSettings: Content description for a button, that collapses ambient volume sliders [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_collapse_controls">Collapse to unified control</string>
+    <!-- QuickSettings: Content description for a button, that mute ambient volume [CHAR_LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_mute">Mute surroundings</string>
+    <!-- QuickSettings: Content description for a button, that unmute ambient volume [CHAR LIMIT=NONE] -->
+    <string name="hearing_devices_ambient_unmute">Unmute surroundings</string>
     <!-- QuickSettings: Title for related tools of hearing. [CHAR LIMIT=40]-->
     <string name="hearing_devices_tools_label">Tools</string>
     <!-- QuickSettings: Tool name for hearing devices dialog related tools [CHAR LIMIT=40] [BACKUP_MESSAGE_ID=8916875614623730005]-->
@@ -2504,14 +2519,14 @@
     <!-- Accessibility description of action to remove QS tile on click. It will read as "Double-tap to remove tile" in screen readers [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_remove_tile_action">remove tile</string>
 
-    <!-- Accessibility action of action to add QS tile to end. It will read as "Double-tap to add tile to end" in screen readers [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_tile_add_action">add tile to end</string>
+    <!-- Accessibility action of action to add QS tile to end. It will read as "Double-tap to add tile to the last position" in screen readers [CHAR LIMIT=NONE] -->
+    <string name="accessibility_qs_edit_tile_add_action">add tile to the last position</string>
 
     <!-- Accessibility action for context menu to move QS tile [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_tile_start_move">Move tile</string>
 
-    <!-- Accessibility action for context menu to add QS tile [CHAR LIMIT=NONE] -->
-    <string name="accessibility_qs_edit_tile_start_add">Add tile</string>
+    <!-- Accessibility action for context menu to add QS tile to a position [CHAR LIMIT=NONE] -->
+    <string name="accessibility_qs_edit_tile_start_add">Add tile to desired position</string>
 
     <!-- Accessibility description when QS tile is to be moved, indicating the destination position [CHAR LIMIT=NONE] -->
     <string name="accessibility_qs_edit_tile_move_to_position">Move to <xliff:g id="position" example="5">%1$d</xliff:g></string>
@@ -2564,7 +2579,7 @@
     <string name="accessibility_quick_settings_open_settings">Open <xliff:g name="page" example="Bluetooth">%s</xliff:g> settings.</string>
 
     <!-- accessibility label for button to edit quick settings [CHAR LIMIT=NONE] -->
-    <string name="accessibility_quick_settings_edit">Edit order of settings.</string>
+    <string name="accessibility_quick_settings_edit">Edit order of Quick Settings.</string>
 
     <!-- accessibility label for button to open power menu [CHAR LIMIT=NONE] -->
     <string name="accessibility_quick_settings_power_menu">Power menu</string>
@@ -3192,8 +3207,6 @@
     <string name="media_output_dialog_connect_failed">Can\'t switch. Tap to try again.</string>
     <!-- Title for connecting item [CHAR LIMIT=60] -->
     <string name="media_output_dialog_pairing_new">Connect a device</string>
-    <!-- Title for launch app [CHAR LIMIT=60] -->
-    <string name="media_output_dialog_launch_app_text">To cast this session, please open the app.</string>
     <!-- App name when can't get app name [CHAR LIMIT=60] -->
     <string name="media_output_dialog_unknown_launch_app_name">Unknown app</string>
     <!-- Button text for stopping casting [CHAR LIMIT=60] -->
@@ -3354,8 +3367,8 @@
     <!-- Accessibility announcement to inform user to unlock using the fingerprint sensor [CHAR LIMIT=NONE] -->
     <string name="accessibility_fingerprint_bouncer">Authentication required. Touch the fingerprint sensor to authenticate.</string>
 
-    <!-- Content description for a chip in the status bar showing that the user is currently on a phone call. [CHAR LIMIT=NONE] -->
-    <string name="ongoing_phone_call_content_description">Ongoing phone call</string>
+    <!-- Content description for a chip in the status bar showing that the user is currently on a call. [CHAR LIMIT=NONE] -->
+    <string name="ongoing_call_content_description">Ongoing call</string>
 
     <!-- Provider Model: Default title of the mobile network in the mobile layout. [CHAR LIMIT=50] -->
     <string name="mobile_data_settings_title">Mobile data</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3156a50..0503dbf 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -73,6 +73,15 @@
     <style name="StatusBar" />
     <style name="StatusBar.Chip" />
 
+    <style name="StatusBar.Chip.RootView">
+        <item name="android:layout_width">wrap_content</item>
+        <!-- Have the root chip view match the parent height so that we get a larger touch area for
+             the chip. -->
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">center_vertical|start</item>
+        <item name="android:layout_marginStart">5dp</item>
+    </style>
+
     <style name="StatusBar.Chip.Text">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
@@ -91,7 +100,6 @@
         <item name="android:ellipsize">none</item>
         <item name="android:requiresFadingEdge">horizontal</item>
         <item name="android:fadingEdgeLength">@dimen/ongoing_activity_chip_text_fading_edge_length</item>
-        <item name="android:maxWidth">@dimen/ongoing_activity_chip_max_text_width</item>
     </style>
 
     <style name="Chipbar" />
@@ -559,15 +567,18 @@
     <style name="SystemUI.Material3.Slider.Volume">
         <item name="trackHeight">40dp</item>
         <item name="thumbHeight">52dp</item>
+        <item name="trackCornerSize">12dp</item>
+        <item name="trackInsideCornerSize">2dp</item>
+        <item name="trackStopIndicatorSize">6dp</item>
     </style>
 
     <style name="SystemUI.Material3.Slider" parent="@style/Widget.Material3.Slider">
         <item name="labelStyle">@style/Widget.Material3.Slider.Label</item>
-        <item name="thumbColor">@color/slider_thumb_color</item>
-        <item name="tickColorActive">@color/slider_inactive_track_color</item>
-        <item name="tickColorInactive">@color/slider_active_track_color</item>
-        <item name="trackColorActive">@color/slider_active_track_color</item>
-        <item name="trackColorInactive">@color/slider_inactive_track_color</item>
+        <item name="thumbColor">@androidprv:color/materialColorPrimary</item>
+        <item name="tickColorActive">@androidprv:color/materialColorSurfaceContainerHighest</item>
+        <item name="tickColorInactive">@androidprv:color/materialColorPrimary</item>
+        <item name="trackColorActive">@androidprv:color/materialColorPrimary</item>
+        <item name="trackColorInactive">@androidprv:color/materialColorSurfaceContainerHighest</item>
     </style>
 
     <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"/>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
index 8298397..69f5a79 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginInstance.java
@@ -108,7 +108,8 @@
     }
 
     @Override
-    public synchronized boolean onFail(String className, String methodName, LinkageError failure) {
+    public synchronized boolean onFail(String className, String methodName, Throwable failure) {
+        Log.e(TAG, "Failure from " + mPlugin + ". Disabling Plugin.");
         mHasError = true;
         unloadPlugin();
         mListener.onPluginDetached(this);
@@ -118,7 +119,7 @@
     /** Alerts listener and plugin that the plugin has been created. */
     public synchronized void onCreate() {
         if (mHasError) {
-            log("Previous LinkageError detected for plugin class");
+            log("Previous Fatal Exception detected for plugin class");
             return;
         }
 
@@ -175,7 +176,7 @@
      */
     public synchronized void loadPlugin() {
         if (mHasError) {
-            log("Previous LinkageError detected for plugin class");
+            log("Previous Fatal Exception detected for plugin class");
             return;
         }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index fc536bd..6f13d63 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 
+import static com.android.systemui.Flags.glanceableHubBackAction;
 import static com.android.systemui.shared.Flags.shadeAllowBackGesture;
 
 import android.annotation.LongDef;
@@ -352,6 +353,10 @@
         }
         // Disable back gesture on the hub, but not when the shade is showing.
         if ((sysuiStateFlags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) {
+            // Allow back gesture on Glanceable Hub with back action support.
+            if (glanceableHubBackAction()) {
+                return false;
+            }
             // Use QS expanded signal as the notification panel is always considered visible
             // expanded when on the lock screen and when opening hub over lock screen. This does
             // mean that back gesture is disabled when opening shade over hub while in portrait
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
index f9fe67a..c13bb3e 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsFactory.kt
@@ -67,7 +67,7 @@
         namespace: String = "systemui",
         default: Boolean = false
     ): SysPropBooleanFlag {
-        val flag = SysPropBooleanFlag(name = name, namespace = "systemui", default = default)
+        val flag = SysPropBooleanFlag(name = name, namespace, default = default)
         checkForDupesAndAdd(flag)
         return flag
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 5af80cb..71b622a 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -43,7 +43,6 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags.REGION_SAMPLING
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
@@ -85,8 +84,8 @@
 import kotlinx.coroutines.flow.merge
 
 /**
- * Controller for a Clock provided by the registry and used on the keyguard. Instantiated by
- * [KeyguardClockSwitchController]. Functionality is forked from [AnimatableClockController].
+ * Controller for a Clock provided by the registry and used on the keyguard. Functionality is forked
+ * from [AnimatableClockController].
  */
 open class ClockEventController
 @Inject
@@ -348,14 +347,6 @@
         object : KeyguardUpdateMonitorCallback() {
             override fun onKeyguardVisibilityChanged(visible: Boolean) {
                 isKeyguardVisible = visible
-                if (!MigrateClocksToBlueprint.isEnabled) {
-                    if (!isKeyguardVisible) {
-                        clock?.run {
-                            smallClock.animations.doze(if (isDozing) 1f else 0f)
-                            largeClock.animations.doze(if (isDozing) 1f else 0f)
-                        }
-                    }
-                }
 
                 if (visible) {
                     refreshTime()
@@ -388,10 +379,6 @@
             }
 
             private fun refreshTime() {
-                if (!MigrateClocksToBlueprint.isEnabled) {
-                    return
-                }
-
                 clock?.smallClock?.events?.onTimeTick()
                 clock?.largeClock?.events?.onTimeTick()
             }
@@ -483,14 +470,10 @@
                     if (ModesUi.isEnabled) {
                         listenForDnd(this)
                     }
-                    if (MigrateClocksToBlueprint.isEnabled) {
-                        listenForDozeAmountTransition(this)
-                        listenForAnyStateToAodTransition(this)
-                        listenForAnyStateToLockscreenTransition(this)
-                        listenForAnyStateToDozingTransition(this)
-                    } else {
-                        listenForDozeAmount(this)
-                    }
+                    listenForDozeAmountTransition(this)
+                    listenForAnyStateToAodTransition(this)
+                    listenForAnyStateToLockscreenTransition(this)
+                    listenForAnyStateToDozingTransition(this)
                 }
             }
         smallTimeListener?.update(shouldTimeListenerRun)
@@ -596,11 +579,6 @@
     }
 
     @VisibleForTesting
-    internal fun listenForDozeAmount(scope: CoroutineScope): Job {
-        return scope.launch { keyguardInteractor.dozeAmount.collect { handleDoze(it) } }
-    }
-
-    @VisibleForTesting
     internal fun listenForDozeAmountTransition(scope: CoroutineScope): Job {
         return scope.launch {
             merge(
@@ -695,8 +673,7 @@
             isRunning = true
             when (clockFace.config.tickRate) {
                 ClockTickRate.PER_MINUTE -> {
-                    // Handled by KeyguardClockSwitchController and
-                    // by KeyguardUpdateMonitorCallback#onTimeChanged.
+                    // Handled by KeyguardUpdateMonitorCallback#onTimeChanged.
                 }
                 ClockTickRate.PER_SECOND -> executor.execute(secondsRunnable)
                 ClockTickRate.PER_FRAME -> {
diff --git a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
index df77a58..3f332f7 100644
--- a/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ConnectedDisplayKeyguardPresentation.kt
@@ -23,14 +23,11 @@
 import android.os.Bundle
 import android.view.Display
 import android.view.Gravity
-import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.view.WindowManager
 import android.widget.FrameLayout
 import android.widget.FrameLayout.LayoutParams
-import com.android.keyguard.dagger.KeyguardStatusViewComponent
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.plugins.clocks.ClockController
 import com.android.systemui.plugins.clocks.ClockFaceController
 import com.android.systemui.res.R
@@ -45,7 +42,6 @@
 constructor(
     @Assisted display: Display,
     context: Context,
-    private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
     private val clockRegistry: ClockRegistry,
     private val clockEventController: ClockEventController,
 ) :
@@ -53,12 +49,11 @@
         context,
         display,
         R.style.Theme_SystemUI_KeyguardPresentation,
-        WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
+        WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
     ) {
 
     private lateinit var rootView: FrameLayout
     private var clock: View? = null
-    private lateinit var keyguardStatusViewController: KeyguardStatusViewController
     private lateinit var faceController: ClockFaceController
     private lateinit var clockFrame: FrameLayout
 
@@ -82,7 +77,7 @@
                 oldLeft: Int,
                 oldTop: Int,
                 oldRight: Int,
-                oldBottom: Int
+                oldBottom: Int,
             ) {
                 clock?.let {
                     faceController.events.onTargetRegionChanged(
@@ -95,11 +90,7 @@
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
-        if (MigrateClocksToBlueprint.isEnabled) {
-            onCreateV2()
-        } else {
-            onCreate()
-        }
+        onCreateV2()
     }
 
     fun onCreateV2() {
@@ -112,39 +103,15 @@
         setClock(clockRegistry.createCurrentClock())
     }
 
-    fun onCreate() {
-        setContentView(
-            LayoutInflater.from(context)
-                .inflate(R.layout.keyguard_clock_presentation, /* root= */ null)
-        )
-
-        setFullscreen()
-
-        clock = requireViewById(R.id.clock)
-        keyguardStatusViewController =
-            keyguardStatusViewComponentFactory
-                .build(clock as KeyguardStatusView, display)
-                .keyguardStatusViewController
-                .apply {
-                    setDisplayedOnSecondaryDisplay()
-                    init()
-                }
-    }
-
     override fun onAttachedToWindow() {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            clockRegistry.registerClockChangeListener(clockChangedListener)
-            clockEventController.registerListeners(clock!!)
-
-            faceController.animations.enter()
-        }
+        clockRegistry.registerClockChangeListener(clockChangedListener)
+        clockEventController.registerListeners(clock!!)
+        faceController.animations.enter()
     }
 
     override fun onDetachedFromWindow() {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            clockEventController.unregisterListeners()
-            clockRegistry.unregisterClockChangeListener(clockChangedListener)
-        }
+        clockEventController.unregisterListeners()
+        clockRegistry.unregisterClockChangeListener(clockChangedListener)
 
         super.onDetachedFromWindow()
     }
@@ -166,7 +133,7 @@
                 context.resources.getDimensionPixelSize(R.dimen.keyguard_presentation_width),
                 WRAP_CONTENT,
                 Gravity.CENTER,
-            )
+            ),
         )
 
         clockEventController.clock = clockController
@@ -190,8 +157,6 @@
     @AssistedFactory
     interface Factory {
         /** Creates a new [Presentation] for the given [display]. */
-        fun create(
-            display: Display,
-        ): ConnectedDisplayKeyguardPresentation
+        fun create(display: Display): ConnectedDisplayKeyguardPresentation
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
deleted file mode 100644
index f7db48a..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.keyguard;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.TextView;
-
-import com.android.systemui.res.R;
-
-/**
- * Replaces fancy colons with regular colons. Only works on TextViews.
- */
-class KeyguardClockAccessibilityDelegate extends View.AccessibilityDelegate {
-    private final String mFancyColon;
-
-    public KeyguardClockAccessibilityDelegate(Context context) {
-        mFancyColon = context.getString(R.string.keyguard_fancy_colon);
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(host, event);
-        if (TextUtils.isEmpty(mFancyColon)) {
-            return;
-        }
-        CharSequence text = event.getContentDescription();
-        if (!TextUtils.isEmpty(text)) {
-            event.setContentDescription(replaceFancyColon(text));
-        }
-    }
-
-    @Override
-    public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
-        if (TextUtils.isEmpty(mFancyColon)) {
-            super.onPopulateAccessibilityEvent(host, event);
-        } else {
-            CharSequence text = ((TextView) host).getText();
-            if (!TextUtils.isEmpty(text)) {
-                event.getText().add(replaceFancyColon(text));
-            }
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(host, info);
-        if (TextUtils.isEmpty(mFancyColon)) {
-            return;
-        }
-        if (!TextUtils.isEmpty(info.getText())) {
-            info.setText(replaceFancyColon(info.getText()));
-        }
-        if (!TextUtils.isEmpty(info.getContentDescription())) {
-            info.setContentDescription(replaceFancyColon(info.getContentDescription()));
-        }
-    }
-
-    private CharSequence replaceFancyColon(CharSequence text) {
-        if (TextUtils.isEmpty(mFancyColon)) {
-            return text;
-        }
-        return text.toString().replace(mFancyColon, ":");
-    }
-
-    public static boolean isNeeded(Context context) {
-        return !TextUtils.isEmpty(context.getString(R.string.keyguard_fancy_colon));
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockFrame.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardClockFrame.kt
deleted file mode 100644
index 1cb8e43..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockFrame.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.android.keyguard
-
-import android.content.Context
-import android.graphics.Canvas
-import android.util.AttributeSet
-import android.view.View
-import android.widget.FrameLayout
-
-class KeyguardClockFrame(
-    context: Context,
-    attrs: AttributeSet,
-) : FrameLayout(context, attrs) {
-    private var drawAlpha: Int = 255
-
-    protected override fun onSetAlpha(alpha: Int): Boolean {
-        // Ignore alpha passed from View, prefer to compute it from set values
-        drawAlpha = (255 * this.alpha * transitionAlpha).toInt()
-        return true
-    }
-
-    protected override fun dispatchDraw(canvas: Canvas) {
-        saveCanvasAlpha(this, canvas, drawAlpha) { super.dispatchDraw(it) }
-    }
-
-    companion object {
-        @JvmStatic
-        fun saveCanvasAlpha(view: View, canvas: Canvas, alpha: Int, drawFunc: (Canvas) -> Unit) {
-            if (alpha <= 0) {
-                // Zero Alpha -> skip drawing phase
-                return
-            }
-
-            if (alpha >= 255) {
-                // Max alpha -> no need for layer
-                drawFunc(canvas)
-                return
-            }
-
-            // Find x & y of view on screen
-            var (x, y) =
-                run {
-                    val locationOnScreen = IntArray(2)
-                    view.getLocationOnScreen(locationOnScreen)
-                    Pair(locationOnScreen[0].toFloat(), locationOnScreen[1].toFloat())
-                }
-
-            val restoreTo =
-                canvas.saveLayerAlpha(-1f * x, -1f * y, x + view.width, y + view.height, alpha)
-            drawFunc(canvas)
-            canvas.restoreToCount(restoreTo)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
deleted file mode 100644
index 71d4e9a..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ /dev/null
@@ -1,501 +0,0 @@
-package com.android.keyguard;
-
-import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN;
-import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN;
-import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.RelativeLayout;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-import androidx.core.content.res.ResourcesCompat;
-
-import com.android.app.animation.Interpolators;
-import com.android.keyguard.dagger.KeyguardStatusViewScope;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
-import com.android.systemui.log.LogBuffer;
-import com.android.systemui.log.core.LogLevel;
-import com.android.systemui.plugins.clocks.ClockController;
-import com.android.systemui.res.R;
-import com.android.systemui.shared.clocks.DefaultClockController;
-
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
- */
-@KeyguardStatusViewScope
-public class KeyguardClockSwitch extends RelativeLayout {
-
-    private static final String TAG = "KeyguardClockSwitch";
-    public static final String MISSING_CLOCK_ID = "CLOCK_MISSING";
-
-    private static final long CLOCK_OUT_MILLIS = 133;
-    private static final long CLOCK_IN_MILLIS = 167;
-    public static final long CLOCK_IN_START_DELAY_MILLIS = 133;
-    private static final long STATUS_AREA_START_DELAY_MILLIS = 0;
-    private static final long STATUS_AREA_MOVE_UP_MILLIS = 967;
-    private static final long STATUS_AREA_MOVE_DOWN_MILLIS = 467;
-    private static final float SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER = 1.4f;
-    private static final float SMARTSPACE_TOP_PADDING_MULTIPLIER = 2.625f;
-
-    @IntDef({LARGE, SMALL})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ClockSize { }
-
-    public static final int LARGE = 0;
-    public static final int SMALL = 1;
-    // compensate for translation of parents subject to device screen
-    // In this case, the translation comes from KeyguardStatusView
-    public int screenOffsetYPadding = 0;
-
-    /** Returns a region for the large clock to position itself, based on the given parent. */
-    public static Rect getLargeClockRegion(ViewGroup parent) {
-        int largeClockTopMargin = parent.getResources()
-                .getDimensionPixelSize(
-                        com.android.systemui.customization.R.dimen.keyguard_large_clock_top_margin);
-        int targetHeight = parent.getResources()
-                .getDimensionPixelSize(
-                        com.android.systemui.customization.R.dimen.large_clock_text_size)
-                * 2;
-        int top = parent.getHeight() / 2 - targetHeight / 2
-                + largeClockTopMargin / 2;
-        return new Rect(
-                parent.getLeft(),
-                top,
-                parent.getRight(),
-                top + targetHeight);
-    }
-
-    /** Returns a region for the small clock to position itself, based on the given parent. */
-    public static Rect getSmallClockRegion(ViewGroup parent) {
-        int targetHeight = parent.getResources()
-                .getDimensionPixelSize(
-                        com.android.systemui.customization.R.dimen.small_clock_text_size);
-        return new Rect(
-                parent.getLeft(),
-                parent.getTop(),
-                parent.getRight(),
-                parent.getTop() + targetHeight);
-    }
-
-    /**
-     * Frame for small/large clocks
-     */
-    private KeyguardClockFrame mSmallClockFrame;
-    private KeyguardClockFrame mLargeClockFrame;
-    private ClockController mClock;
-
-    // It's bc_smartspace_view, assigned by KeyguardClockSwitchController
-    // to get the top padding for translating smartspace for weather clock
-    private View mSmartspace;
-
-    // Smartspace in weather clock is translated by this value
-    // to compensate for the position invisible dateWeatherView
-    private int mSmartspaceTop = -1;
-
-    private KeyguardStatusAreaView mStatusArea;
-    private int mSmartspaceTopOffset;
-    private float mWeatherClockSmartspaceScaling = 1f;
-    private int mWeatherClockSmartspaceTranslateX = 0;
-    private int mWeatherClockSmartspaceTranslateY = 0;
-    private int mDrawAlpha = 255;
-
-    private int mStatusBarHeight = 0;
-
-    /**
-     * Maintain state so that a newly connected plugin can be initialized.
-     */
-    private float mDarkAmount;
-    private boolean mSplitShadeCentered = false;
-
-    /**
-     * Indicates which clock is currently displayed - should be one of {@link ClockSize}.
-     * Use null to signify it is uninitialized.
-     */
-    @ClockSize private Integer mDisplayedClockSize = null;
-
-    @VisibleForTesting AnimatorSet mClockInAnim = null;
-    @VisibleForTesting AnimatorSet mClockOutAnim = null;
-    @VisibleForTesting AnimatorSet mStatusAreaAnim = null;
-
-    private int mClockSwitchYAmount;
-    @VisibleForTesting boolean mChildrenAreLaidOut = false;
-    @VisibleForTesting boolean mAnimateOnLayout = true;
-    private LogBuffer mLogBuffer = null;
-
-    public KeyguardClockSwitch(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    /**
-     * Apply dp changes on configuration change
-     */
-    public void onConfigChanged() {
-        mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
-                R.dimen.keyguard_clock_switch_y_shift);
-        mSmartspaceTopOffset = (int) (mContext.getResources().getDimensionPixelSize(
-                com.android.systemui.customization.R.dimen.keyguard_smartspace_top_offset)
-                * mContext.getResources().getConfiguration().fontScale
-                / mContext.getResources().getDisplayMetrics().density
-                * SMARTSPACE_TOP_PADDING_MULTIPLIER);
-        mWeatherClockSmartspaceScaling = ResourcesCompat.getFloat(
-                mContext.getResources(), R.dimen.weather_clock_smartspace_scale);
-        mWeatherClockSmartspaceTranslateX = mContext.getResources().getDimensionPixelSize(
-                R.dimen.weather_clock_smartspace_translateX);
-        mWeatherClockSmartspaceTranslateY = mContext.getResources().getDimensionPixelSize(
-                R.dimen.weather_clock_smartspace_translateY);
-        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
-                R.dimen.status_bar_height);
-        updateStatusArea(/* animate= */false);
-    }
-
-    /** Get bc_smartspace_view from KeyguardClockSwitchController
-     * Use its top to decide the translation value */
-    public void setSmartspace(View smartspace) {
-        mSmartspace = smartspace;
-    }
-
-    /** Sets whether the large clock is being shown on a connected display. */
-    public void setLargeClockOnSecondaryDisplay(boolean onSecondaryDisplay) {
-        if (mClock != null) {
-            mClock.getLargeClock().getEvents().onSecondaryDisplayChanged(onSecondaryDisplay);
-        }
-    }
-
-    /**
-     * Enable or disable split shade specific positioning
-     */
-    public void setSplitShadeCentered(boolean splitShadeCentered) {
-        if (mSplitShadeCentered != splitShadeCentered) {
-            mSplitShadeCentered = splitShadeCentered;
-            updateStatusArea(/* animate= */true);
-        }
-    }
-
-    public boolean getSplitShadeCentered() {
-        return mSplitShadeCentered;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mSmallClockFrame = findViewById(
-                    com.android.systemui.customization.R.id.lockscreen_clock_view);
-            mLargeClockFrame = findViewById(
-                    com.android.systemui.customization.R.id.lockscreen_clock_view_large);
-            mStatusArea = findViewById(R.id.keyguard_status_area);
-        } else {
-            removeView(findViewById(
-                    com.android.systemui.customization.R.id.lockscreen_clock_view));
-            removeView(findViewById(
-                    com.android.systemui.customization.R.id.lockscreen_clock_view_large));
-        }
-        onConfigChanged();
-    }
-
-    @Override
-    protected boolean onSetAlpha(int alpha) {
-        mDrawAlpha = alpha;
-        return true;
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        KeyguardClockFrame.saveCanvasAlpha(
-                this, canvas, mDrawAlpha,
-                c -> {
-                    super.dispatchDraw(c);
-                    return kotlin.Unit.INSTANCE;
-                });
-    }
-
-    public void setLogBuffer(LogBuffer logBuffer) {
-        mLogBuffer = logBuffer;
-    }
-
-    public LogBuffer getLogBuffer() {
-        return mLogBuffer;
-    }
-
-    /** Returns the id of the currently rendering clock */
-    public String getClockId() {
-        if (mClock == null) {
-            return MISSING_CLOCK_ID;
-        }
-        return mClock.getConfig().getId();
-    }
-
-    void setClock(ClockController clock, int statusBarState) {
-        mClock = clock;
-
-        // Disconnect from existing plugin.
-        mSmallClockFrame.removeAllViews();
-        mLargeClockFrame.removeAllViews();
-
-        if (clock == null) {
-            if (mLogBuffer != null) {
-                mLogBuffer.log(TAG, LogLevel.ERROR, "No clock being shown");
-            }
-            return;
-        }
-
-        // Attach small and big clock views to hierarchy.
-        if (mLogBuffer != null) {
-            mLogBuffer.log(TAG, LogLevel.INFO, "Attached new clock views to switch");
-        }
-        mSmallClockFrame.addView(clock.getSmallClock().getView());
-        mLargeClockFrame.addView(clock.getLargeClock().getView());
-        updateClockTargetRegions();
-        updateStatusArea(/* animate= */false);
-    }
-
-    private void updateStatusArea(boolean animate) {
-        if (mDisplayedClockSize != null && mChildrenAreLaidOut) {
-            updateClockViews(mDisplayedClockSize == LARGE, animate);
-        }
-    }
-
-    void updateClockTargetRegions() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        if (mClock != null) {
-            if (mSmallClockFrame.isLaidOut()) {
-                Rect targetRegion = getSmallClockRegion(mSmallClockFrame);
-                mClock.getSmallClock().getEvents().onTargetRegionChanged(targetRegion);
-            }
-
-            if (mLargeClockFrame.isLaidOut()) {
-                Rect targetRegion = getLargeClockRegion(mLargeClockFrame);
-                if (mClock instanceof DefaultClockController) {
-                    mClock.getLargeClock().getEvents().onTargetRegionChanged(
-                            targetRegion);
-                } else {
-                    mClock.getLargeClock().getEvents().onTargetRegionChanged(
-                            new Rect(
-                                    targetRegion.left,
-                                    targetRegion.top - screenOffsetYPadding,
-                                    targetRegion.right,
-                                    targetRegion.bottom - screenOffsetYPadding));
-                }
-            }
-        }
-    }
-
-    private void updateClockViews(boolean useLargeClock, boolean animate) {
-        if (mLogBuffer != null) {
-            mLogBuffer.log(TAG, LogLevel.DEBUG, (msg) -> {
-                msg.setBool1(useLargeClock);
-                msg.setBool2(animate);
-                msg.setBool3(mChildrenAreLaidOut);
-                return kotlin.Unit.INSTANCE;
-            }, (msg) -> "updateClockViews"
-                    + "; useLargeClock=" + msg.getBool1()
-                    + "; animate=" + msg.getBool2()
-                    + "; mChildrenAreLaidOut=" + msg.getBool3());
-        }
-
-        if (mClockInAnim != null) mClockInAnim.cancel();
-        if (mClockOutAnim != null) mClockOutAnim.cancel();
-        if (mStatusAreaAnim != null) mStatusAreaAnim.cancel();
-
-        mClockInAnim = null;
-        mClockOutAnim = null;
-        mStatusAreaAnim = null;
-
-        View in, out;
-        // statusAreaYTranslation uses for the translation for both mStatusArea and mSmallClockFrame
-        // statusAreaClockTranslateY only uses for mStatusArea
-        float statusAreaYTranslation, statusAreaClockScale = 1f;
-        float statusAreaClockTranslateX = 0f, statusAreaClockTranslateY = 0f;
-        float clockInYTranslation, clockOutYTranslation;
-        if (useLargeClock) {
-            out = mSmallClockFrame;
-            in = mLargeClockFrame;
-            if (indexOfChild(in) == -1) addView(in, 0);
-            statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop()
-                    + mSmartspaceTopOffset;
-            // TODO: Load from clock config when less risky
-            if (mClock != null
-                    && mClock.getLargeClock().getConfig().getHasCustomWeatherDataDisplay()) {
-                statusAreaClockScale = mWeatherClockSmartspaceScaling;
-                statusAreaClockTranslateX = mWeatherClockSmartspaceTranslateX;
-                if (mSplitShadeCentered) {
-                    statusAreaClockTranslateX *= SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER;
-                }
-
-                // On large weather clock,
-                // top padding for time is status bar height from top of the screen.
-                // On small one,
-                // it's screenOffsetYPadding (translationY for KeyguardStatusView),
-                // Cause smartspace is positioned according to the smallClockFrame
-                // we need to translate the difference between bottom of large clock and small clock
-                // Also, we need to counter offset the empty date weather view, mSmartspaceTop
-                // mWeatherClockSmartspaceTranslateY is only for Felix
-                statusAreaClockTranslateY = mStatusBarHeight - 0.6F *  mSmallClockFrame.getHeight()
-                        - mSmartspaceTop - screenOffsetYPadding
-                        - statusAreaYTranslation + mWeatherClockSmartspaceTranslateY;
-            }
-            clockInYTranslation = 0;
-            clockOutYTranslation = 0; // Small clock translation is handled with statusArea
-        } else {
-            in = mSmallClockFrame;
-            out = mLargeClockFrame;
-            statusAreaYTranslation = 0f;
-            clockInYTranslation = 0f;
-            clockOutYTranslation = mClockSwitchYAmount * -1f;
-
-            // Must remove in order for notifications to appear in the proper place, ideally this
-            // would happen after the out animation runs, but we can't guarantee that the
-            // nofications won't enter only after the out animation runs.
-            removeView(out);
-        }
-
-        if (!animate) {
-            out.setAlpha(0f);
-            out.setTranslationY(clockOutYTranslation);
-            out.setVisibility(INVISIBLE);
-            in.setAlpha(1f);
-            in.setTranslationY(clockInYTranslation);
-            in.setVisibility(VISIBLE);
-            mStatusArea.setScaleX(statusAreaClockScale);
-            mStatusArea.setScaleY(statusAreaClockScale);
-            mStatusArea.setTranslateXFromClockDesign(statusAreaClockTranslateX);
-            mStatusArea.setTranslateYFromClockDesign(statusAreaClockTranslateY);
-            mStatusArea.setTranslateYFromClockSize(statusAreaYTranslation);
-            mSmallClockFrame.setTranslationY(statusAreaYTranslation);
-            return;
-        }
-
-        mClockOutAnim = new AnimatorSet();
-        mClockOutAnim.setDuration(CLOCK_OUT_MILLIS);
-        mClockOutAnim.setInterpolator(Interpolators.LINEAR);
-        mClockOutAnim.playTogether(
-                ObjectAnimator.ofFloat(out, ALPHA, 0f),
-                ObjectAnimator.ofFloat(out, TRANSLATION_Y, clockOutYTranslation));
-        mClockOutAnim.addListener(new AnimatorListenerAdapter() {
-            public void onAnimationEnd(Animator animation) {
-                if (mClockOutAnim == animation) {
-                    out.setVisibility(INVISIBLE);
-                    mClockOutAnim = null;
-                }
-            }
-        });
-
-        in.setVisibility(View.VISIBLE);
-        mClockInAnim = new AnimatorSet();
-        mClockInAnim.setDuration(CLOCK_IN_MILLIS);
-        mClockInAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-        mClockInAnim.playTogether(
-                ObjectAnimator.ofFloat(in, ALPHA, 1f),
-                ObjectAnimator.ofFloat(in, TRANSLATION_Y, clockInYTranslation));
-        mClockInAnim.setStartDelay(CLOCK_IN_START_DELAY_MILLIS);
-        mClockInAnim.addListener(new AnimatorListenerAdapter() {
-            public void onAnimationEnd(Animator animation) {
-                if (mClockInAnim == animation) {
-                    mClockInAnim = null;
-                }
-            }
-        });
-
-        mStatusAreaAnim = new AnimatorSet();
-        mStatusAreaAnim.setStartDelay(STATUS_AREA_START_DELAY_MILLIS);
-        mStatusAreaAnim.setDuration(
-                useLargeClock ? STATUS_AREA_MOVE_UP_MILLIS : STATUS_AREA_MOVE_DOWN_MILLIS);
-        mStatusAreaAnim.setInterpolator(Interpolators.EMPHASIZED);
-        mStatusAreaAnim.playTogether(
-                ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_SIZE.getProperty(),
-                        statusAreaYTranslation),
-                ObjectAnimator.ofFloat(mSmallClockFrame, TRANSLATION_Y, statusAreaYTranslation),
-                ObjectAnimator.ofFloat(mStatusArea, SCALE_X, statusAreaClockScale),
-                ObjectAnimator.ofFloat(mStatusArea, SCALE_Y, statusAreaClockScale),
-                ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_X_CLOCK_DESIGN.getProperty(),
-                        statusAreaClockTranslateX),
-                ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_DESIGN.getProperty(),
-                        statusAreaClockTranslateY));
-        mStatusAreaAnim.addListener(new AnimatorListenerAdapter() {
-            public void onAnimationEnd(Animator animation) {
-                if (mStatusAreaAnim == animation) {
-                    mStatusAreaAnim = null;
-                }
-            }
-        });
-
-        mClockInAnim.start();
-        mClockOutAnim.start();
-        mStatusAreaAnim.start();
-    }
-
-    /**
-     * Display the desired clock and hide the other one
-     *
-     * @return true if desired clock appeared and false if it was already visible
-     */
-    boolean switchToClock(@ClockSize int clockSize, boolean animate) {
-        if (mDisplayedClockSize != null && clockSize == mDisplayedClockSize) {
-            return false;
-        }
-
-        // let's make sure clock is changed only after all views were laid out so we can
-        // translate them properly
-        if (mChildrenAreLaidOut) {
-            updateClockViews(clockSize == LARGE, animate);
-        }
-
-        mDisplayedClockSize = clockSize;
-        return true;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        // TODO: b/305022530
-        if (mClock != null && mClock.getConfig().getId().equals("DIGITAL_CLOCK_METRO")) {
-            mClock.getSmallClock().getEvents().onThemeChanged(mClock.getSmallClock().getTheme());
-            mClock.getLargeClock().getEvents().onThemeChanged(mClock.getLargeClock().getTheme());
-        }
-
-        if (changed) {
-            post(() -> updateClockTargetRegions());
-        }
-
-        if (mSmartspace != null && mSmartspaceTop != mSmartspace.getTop()
-                && mDisplayedClockSize != null) {
-            mSmartspaceTop = mSmartspace.getTop();
-            post(() -> updateClockViews(mDisplayedClockSize == LARGE, mAnimateOnLayout));
-        }
-
-        if (mDisplayedClockSize != null && !mChildrenAreLaidOut) {
-            post(() -> updateClockViews(mDisplayedClockSize == LARGE, mAnimateOnLayout));
-        }
-        mChildrenAreLaidOut = true;
-    }
-
-    public void dump(PrintWriter pw, String[] args) {
-        pw.println("KeyguardClockSwitch:");
-        pw.println("  mSmallClockFrame = " + mSmallClockFrame);
-        if (mSmallClockFrame != null) {
-            pw.println("  mSmallClockFrame.alpha = " + mSmallClockFrame.getAlpha());
-        }
-        pw.println("  mLargeClockFrame = " + mLargeClockFrame);
-        if (mLargeClockFrame != null) {
-            pw.println("  mLargeClockFrame.alpha = " + mLargeClockFrame.getAlpha());
-        }
-        pw.println("  mStatusArea = " + mStatusArea);
-        pw.println("  mDisplayedClockSize = " + mDisplayedClockSize);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
deleted file mode 100644
index 0e1eccc..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import static com.android.keyguard.KeyguardClockSwitch.LARGE;
-import static com.android.keyguard.KeyguardClockSwitch.SMALL;
-import static com.android.systemui.Flags.smartspaceRelocateToBottom;
-
-import android.annotation.Nullable;
-import android.database.ContentObserver;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
-import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager;
-import com.android.systemui.log.LogBuffer;
-import com.android.systemui.log.core.LogLevel;
-import com.android.systemui.log.dagger.KeyguardClockLog;
-import com.android.systemui.plugins.clocks.ClockController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.res.R;
-import com.android.systemui.shared.clocks.ClockRegistry;
-import com.android.systemui.shared.regionsampling.RegionSampler;
-import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import com.android.systemui.util.ViewController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.android.systemui.util.settings.SecureSettings;
-
-import kotlinx.coroutines.DisposableHandle;
-
-import java.io.PrintWriter;
-import java.util.Locale;
-import java.util.concurrent.Executor;
-
-import javax.inject.Inject;
-
-/**
- * Injectable controller for {@link KeyguardClockSwitch}.
- */
-public class KeyguardClockSwitchController extends ViewController<KeyguardClockSwitch>
-        implements Dumpable {
-    private static final String TAG = "KeyguardClockSwitchController";
-
-    private final StatusBarStateController mStatusBarStateController;
-    private final ClockRegistry mClockRegistry;
-    private final KeyguardSliceViewController mKeyguardSliceViewController;
-    private final LockscreenSmartspaceController mSmartspaceController;
-    private final SecureSettings mSecureSettings;
-    private final DumpManager mDumpManager;
-    private final ClockEventController mClockEventController;
-    private final LogBuffer mLogBuffer;
-    private FrameLayout mSmallClockFrame; // top aligned clock
-    private FrameLayout mLargeClockFrame; // centered clock
-
-    @KeyguardClockSwitch.ClockSize
-    private int mCurrentClockSize = SMALL;
-
-    private int mKeyguardSmallClockTopMargin = 0;
-    private int mKeyguardLargeClockTopMargin = 0;
-    private int mKeyguardDateWeatherViewInvisibility = View.INVISIBLE;
-    private final ClockRegistry.ClockChangeListener mClockChangedListener;
-
-    private ViewGroup mStatusArea;
-
-    // If the SMARTSPACE flag is set, keyguard_slice_view is replaced by the following views.
-    private ViewGroup mDateWeatherView;
-    private View mWeatherView;
-    private View mSmartspaceView;
-
-    private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
-    private final InWindowLauncherUnlockAnimationManager mInWindowLauncherUnlockAnimationManager;
-
-    private boolean mShownOnSecondaryDisplay = false;
-    private boolean mOnlyClock = false;
-    private KeyguardInteractor mKeyguardInteractor;
-    private KeyguardClockInteractor mKeyguardClockInteractor;
-    private final DelayableExecutor mUiExecutor;
-    private final Executor mBgExecutor;
-    private boolean mCanShowDoubleLineClock = true;
-    private DisposableHandle mAodIconsBindHandle;
-    @Nullable private NotificationIconContainer mAodIconContainer;
-
-    private final ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
-        @Override
-        public void onChange(boolean change) {
-            updateDoubleLineClock();
-        }
-    };
-    private final ContentObserver mShowWeatherObserver = new ContentObserver(null) {
-        @Override
-        public void onChange(boolean change) {
-            setWeatherVisibility();
-        }
-    };
-
-    private final KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener
-            mKeyguardUnlockAnimationListener =
-            new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() {
-                @Override
-                public void onUnlockAnimationFinished() {
-                    // For performance reasons, reset this once the unlock animation ends.
-                    setClipChildrenForUnlock(true);
-                }
-            };
-
-    @Inject
-    public KeyguardClockSwitchController(
-            KeyguardClockSwitch keyguardClockSwitch,
-            StatusBarStateController statusBarStateController,
-            ClockRegistry clockRegistry,
-            KeyguardSliceViewController keyguardSliceViewController,
-            LockscreenSmartspaceController smartspaceController,
-            KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            SecureSettings secureSettings,
-            @Main DelayableExecutor uiExecutor,
-            @Background Executor bgExecutor,
-            DumpManager dumpManager,
-            ClockEventController clockEventController,
-            @KeyguardClockLog LogBuffer logBuffer,
-            KeyguardInteractor keyguardInteractor,
-            KeyguardClockInteractor keyguardClockInteractor,
-            InWindowLauncherUnlockAnimationManager inWindowLauncherUnlockAnimationManager) {
-        super(keyguardClockSwitch);
-        mStatusBarStateController = statusBarStateController;
-        mClockRegistry = clockRegistry;
-        mKeyguardSliceViewController = keyguardSliceViewController;
-        mSmartspaceController = smartspaceController;
-        mSecureSettings = secureSettings;
-        mUiExecutor = uiExecutor;
-        mBgExecutor = bgExecutor;
-        mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
-        mDumpManager = dumpManager;
-        mClockEventController = clockEventController;
-        mLogBuffer = logBuffer;
-        mView.setLogBuffer(mLogBuffer);
-        mKeyguardInteractor = keyguardInteractor;
-        mKeyguardClockInteractor = keyguardClockInteractor;
-        mInWindowLauncherUnlockAnimationManager = inWindowLauncherUnlockAnimationManager;
-
-        mClockChangedListener = new ClockRegistry.ClockChangeListener() {
-            @Override
-            public void onCurrentClockChanged() {
-                if (!MigrateClocksToBlueprint.isEnabled()) {
-                    setClock(mClockRegistry.createCurrentClock());
-                }
-            }
-            @Override
-            public void onAvailableClocksChanged() { }
-        };
-    }
-
-    /**
-     * When set, limits the information shown in an external display.
-     */
-    public void setShownOnSecondaryDisplay(boolean shownOnSecondaryDisplay) {
-        mShownOnSecondaryDisplay = shownOnSecondaryDisplay;
-    }
-
-    /**
-     * Mostly used for alternate displays, limit the information shown
-     *
-     * @deprecated use {@link KeyguardClockSwitchController#setShownOnSecondaryDisplay}
-     */
-    @Deprecated
-    public void setOnlyClock(boolean onlyClock) {
-        mOnlyClock = onlyClock;
-    }
-
-    /**
-     * Used for status view to pass the screen offset from parent view
-     */
-    public void setLockscreenClockY(int clockY) {
-        if (mView.screenOffsetYPadding != clockY) {
-            mView.screenOffsetYPadding = clockY;
-            mView.post(() -> mView.updateClockTargetRegions());
-        }
-    }
-
-    /**
-     * Attach the controller to the view it relates to.
-     */
-    @Override
-    protected void onInit() {
-        mKeyguardSliceViewController.init();
-
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mSmallClockFrame = mView
-                .findViewById(com.android.systemui.customization.R.id.lockscreen_clock_view);
-            mLargeClockFrame = mView
-                .findViewById(com.android.systemui.customization.R.id.lockscreen_clock_view_large);
-        }
-
-        if (!mOnlyClock) {
-            mDumpManager.unregisterDumpable(getClass().getSimpleName()); // unregister previous
-            mDumpManager.registerDumpable(getClass().getSimpleName(), this);
-        }
-    }
-
-    public KeyguardClockSwitch getView() {
-        return mView;
-    }
-
-    private void hideSliceViewAndNotificationIconContainer() {
-        View ksv = mView.findViewById(R.id.keyguard_slice_view);
-        ksv.setVisibility(View.GONE);
-
-        View nic = mView.findViewById(
-                R.id.left_aligned_notification_icon_container);
-        if (nic != null) {
-            nic.setVisibility(View.GONE);
-        }
-    }
-
-    @Override
-    protected void onViewAttached() {
-        mClockRegistry.registerClockChangeListener(mClockChangedListener);
-        setClock(mClockRegistry.createCurrentClock());
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mClockEventController.registerListeners(mView);
-        }
-        mKeyguardSmallClockTopMargin =
-                mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-        mKeyguardLargeClockTopMargin =
-                mView.getResources().getDimensionPixelSize(
-                        com.android.systemui.customization.R.dimen.keyguard_large_clock_top_margin);
-        mKeyguardDateWeatherViewInvisibility =
-                mView.getResources().getInteger(R.integer.keyguard_date_weather_view_invisibility);
-
-        if (mShownOnSecondaryDisplay) {
-            mView.setLargeClockOnSecondaryDisplay(true);
-            mClockEventController.setLargeClockOnSecondaryDisplay(true);
-            displayClock(LARGE, /* animate= */ false);
-            hideSliceViewAndNotificationIconContainer();
-            return;
-        }
-
-        if (mOnlyClock) {
-            hideSliceViewAndNotificationIconContainer();
-            return;
-        }
-        mStatusArea = mView.findViewById(R.id.keyguard_status_area);
-
-        mBgExecutor.execute(() -> {
-            mSecureSettings.registerContentObserverForUserSync(
-                    Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
-                    false, /* notifyForDescendants */
-                    mDoubleLineClockObserver,
-                    UserHandle.USER_ALL
-            );
-
-            mSecureSettings.registerContentObserverForUserSync(
-                    Settings.Secure.LOCK_SCREEN_WEATHER_ENABLED,
-                    false, /* notifyForDescendants */
-                    mShowWeatherObserver,
-                    UserHandle.USER_ALL
-            );
-        });
-
-        updateDoubleLineClock();
-
-        mKeyguardUnlockAnimationController.addKeyguardUnlockAnimationListener(
-                mKeyguardUnlockAnimationListener);
-
-        if (mSmartspaceController.isEnabled()) {
-            View ksv = mView.findViewById(R.id.keyguard_slice_view);
-            int viewIndex = mStatusArea.indexOfChild(ksv);
-            ksv.setVisibility(View.GONE);
-
-            removeViewsFromStatusArea();
-            addSmartspaceView();
-            // TODO(b/261757708): add content observer for the Settings toggle and add/remove
-            //  weather according to the Settings.
-            if (mSmartspaceController.isDateWeatherDecoupled()) {
-                addDateWeatherView();
-            }
-        }
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            setDateWeatherVisibility();
-            setWeatherVisibility();
-        }
-
-    }
-
-    int getNotificationIconAreaHeight() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return 0;
-        } else {
-            return mAodIconContainer != null ? mAodIconContainer.getHeight() : 0;
-        }
-    }
-
-    @Nullable
-    View getAodNotifIconContainer() {
-        return mAodIconContainer;
-    }
-
-    @Override
-    protected void onViewDetached() {
-        mClockRegistry.unregisterClockChangeListener(mClockChangedListener);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mClockEventController.unregisterListeners();
-        }
-        setClock(null);
-
-        mBgExecutor.execute(() -> {
-            mSecureSettings.unregisterContentObserverSync(mDoubleLineClockObserver);
-            mSecureSettings.unregisterContentObserverSync(mShowWeatherObserver);
-        });
-
-        mKeyguardUnlockAnimationController.removeKeyguardUnlockAnimationListener(
-                mKeyguardUnlockAnimationListener);
-    }
-
-    void onLocaleListChanged() {
-        if (mSmartspaceController.isEnabled()) {
-            removeViewsFromStatusArea();
-            addSmartspaceView();
-            if (mSmartspaceController.isDateWeatherDecoupled()) {
-                mDateWeatherView.removeView(mWeatherView);
-                addDateWeatherView();
-                setDateWeatherVisibility();
-                setWeatherVisibility();
-            }
-        }
-    }
-
-    private void addDateWeatherView() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        mDateWeatherView = (ViewGroup) mSmartspaceController.buildAndConnectDateView(mView);
-        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
-                MATCH_PARENT, WRAP_CONTENT);
-        mStatusArea.addView(mDateWeatherView, 0, lp);
-        int startPadding = getContext().getResources().getDimensionPixelSize(
-                R.dimen.below_clock_padding_start);
-        int endPadding = getContext().getResources().getDimensionPixelSize(
-                R.dimen.below_clock_padding_end);
-        mDateWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
-        addWeatherView();
-    }
-
-    private void addWeatherView() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
-                WRAP_CONTENT, WRAP_CONTENT);
-        mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
-        // Place weather right after the date, before the extras
-        final int index = mDateWeatherView.getChildCount() == 0 ? 0 : 1;
-        mDateWeatherView.addView(mWeatherView, index, lp);
-        mWeatherView.setPaddingRelative(0, 0, 4, 0);
-    }
-
-    private void addSmartspaceView() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-
-        if (smartspaceRelocateToBottom()) {
-            return;
-        }
-
-        mSmartspaceView = mSmartspaceController.buildAndConnectView(mView);
-        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
-                MATCH_PARENT, WRAP_CONTENT);
-        mStatusArea.addView(mSmartspaceView, 0, lp);
-        int startPadding = getContext().getResources().getDimensionPixelSize(
-                R.dimen.below_clock_padding_start);
-        int endPadding = getContext().getResources().getDimensionPixelSize(
-                R.dimen.below_clock_padding_end);
-        mSmartspaceView.setPaddingRelative(startPadding, 0, endPadding, 0);
-
-        mKeyguardUnlockAnimationController.setLockscreenSmartspace(mSmartspaceView);
-        mInWindowLauncherUnlockAnimationManager.setLockscreenSmartspace(mSmartspaceView);
-
-        mView.setSmartspace(mSmartspaceView);
-    }
-
-    /**
-     * Apply dp changes on configuration change
-     */
-    public void onConfigChanged() {
-        mView.onConfigChanged();
-        mKeyguardSmallClockTopMargin =
-                mView.getResources().getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-        mKeyguardLargeClockTopMargin =
-                mView.getResources().getDimensionPixelSize(
-                        com.android.systemui.customization.R.dimen.keyguard_large_clock_top_margin);
-        mKeyguardDateWeatherViewInvisibility =
-                mView.getResources().getInteger(R.integer.keyguard_date_weather_view_invisibility);
-        mView.updateClockTargetRegions();
-        setDateWeatherVisibility();
-    }
-
-    /**
-     * Enable or disable split shade center specific positioning
-     */
-    public void setSplitShadeCentered(boolean splitShadeCentered) {
-        mView.setSplitShadeCentered(splitShadeCentered);
-    }
-
-    /**
-     * Set if the split shade is enabled
-     */
-    public void setSplitShadeEnabled(boolean splitShadeEnabled) {
-        mSmartspaceController.setSplitShadeEnabled(splitShadeEnabled);
-    }
-
-    /**
-     * Set which clock should be displayed on the keyguard. The other one will be automatically
-     * hidden.
-     */
-    public void displayClock(@KeyguardClockSwitch.ClockSize int clockSize, boolean animate) {
-        if (!mCanShowDoubleLineClock && clockSize == KeyguardClockSwitch.LARGE) {
-            return;
-        }
-
-        mCurrentClockSize = clockSize;
-        setDateWeatherVisibility();
-
-        ClockController clock = getClock();
-        boolean appeared = mView.switchToClock(clockSize, animate);
-        if (clock != null && animate && appeared && clockSize == LARGE) {
-            mUiExecutor.executeDelayed(() -> clock.getLargeClock().getAnimations().enter(),
-                    KeyguardClockSwitch.CLOCK_IN_START_DELAY_MILLIS);
-        }
-    }
-
-    /**
-     * Animates the clock view between folded and unfolded states
-     */
-    public void animateFoldToAod(float foldFraction) {
-        ClockController clock = getClock();
-        if (clock != null) {
-            clock.getSmallClock().getAnimations().fold(foldFraction);
-            clock.getLargeClock().getAnimations().fold(foldFraction);
-        }
-    }
-
-    /**
-     * Refresh clock. Called in response to TIME_TICK broadcasts.
-     */
-    void refresh() {
-        mLogBuffer.log(TAG, LogLevel.INFO, "refresh");
-        if (mSmartspaceController != null) {
-            mSmartspaceController.requestSmartspaceUpdate();
-        }
-        ClockController clock = getClock();
-        if (clock != null) {
-            clock.getSmallClock().getEvents().onTimeTick();
-            clock.getLargeClock().getEvents().onTimeTick();
-        }
-    }
-
-    /**
-     * Update position of the view, with optional animation. Move the slice view and the clock
-     * slightly towards the center in order to prevent burn-in. Y positioning occurs at the
-     * view parent level. The large clock view will scale instead of using x position offsets, to
-     * keep the clock centered.
-     */
-    void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
-        x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            PropertyAnimator.setProperty(mSmallClockFrame, AnimatableProperty.TRANSLATION_X,
-                    x, props, animate);
-            PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_X,
-                    scale, props, animate);
-            PropertyAnimator.setProperty(mLargeClockFrame, AnimatableProperty.SCALE_Y,
-                    scale, props, animate);
-
-        }
-
-        if (mStatusArea != null) {
-            PropertyAnimator.setProperty(mStatusArea, KeyguardStatusAreaView.TRANSLATE_X_AOD,
-                    x, props, animate);
-        }
-    }
-
-    /**
-     * Get y-bottom position of the currently visible clock on the keyguard.
-     * We can't directly getBottom() because clock changes positions in AOD for burn-in
-     */
-    int getClockBottom(int statusBarHeaderHeight) {
-        ClockController clock = getClock();
-        if (clock == null) {
-            return 0;
-        }
-
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return 0;
-        }
-
-        if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
-            // This gets the expected clock bottom if mLargeClockFrame had a top margin, but it's
-            // top margin only contributed to height and didn't move the top of the view (as this
-            // was the computation previously). As we no longer have a margin, we add this back
-            // into the computation manually.
-            int frameHeight = mLargeClockFrame.getHeight();
-            int clockHeight = clock.getLargeClock().getView().getHeight();
-            return frameHeight / 2 + clockHeight / 2 + mKeyguardLargeClockTopMargin / -2;
-        } else {
-            int clockHeight = clock.getSmallClock().getView().getHeight();
-            return clockHeight + statusBarHeaderHeight + mKeyguardSmallClockTopMargin;
-        }
-    }
-
-    /**
-     * Get the height of the currently visible clock on the keyguard.
-     */
-    int getClockHeight() {
-        ClockController clock = getClock();
-        if (clock == null) {
-            return 0;
-        }
-
-        if (mLargeClockFrame.getVisibility() == View.VISIBLE) {
-            return clock.getLargeClock().getView().getHeight();
-        } else {
-            return clock.getSmallClock().getView().getHeight();
-        }
-    }
-
-    boolean isClockTopAligned() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return mKeyguardClockInteractor.getClockSize().getValue().getLegacyValue() == LARGE;
-        }
-        return mLargeClockFrame.getVisibility() != View.VISIBLE;
-    }
-
-    private void setClock(ClockController clock) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        if (clock != null && mLogBuffer != null) {
-            mLogBuffer.log(TAG, LogLevel.INFO, "New Clock");
-        }
-
-        mClockEventController.setClock(clock);
-        mView.setClock(clock, mStatusBarStateController.getState());
-        setDateWeatherVisibility();
-    }
-
-    @Nullable
-    public ClockController getClock() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return mKeyguardClockInteractor.getCurrentClock().getValue();
-        } else {
-            return mClockEventController.getClock();
-        }
-    }
-
-    private int getCurrentLayoutDirection() {
-        return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
-    }
-
-    private void updateDoubleLineClock() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        mCanShowDoubleLineClock = mSecureSettings.getIntForUser(
-            Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, mView.getResources()
-                    .getInteger(com.android.internal.R.integer.config_doublelineClockDefault),
-            UserHandle.USER_CURRENT) != 0;
-
-        if (!mCanShowDoubleLineClock) {
-            mUiExecutor.execute(() -> displayClock(KeyguardClockSwitch.SMALL,
-                    /* animate */ true));
-        }
-    }
-
-    private void setDateWeatherVisibility() {
-        if (mDateWeatherView != null) {
-            mUiExecutor.execute(() -> {
-                mDateWeatherView.setVisibility(clockHasCustomWeatherDataDisplay()
-                        ? mKeyguardDateWeatherViewInvisibility
-                        : View.VISIBLE);
-            });
-        }
-    }
-
-    private void setWeatherVisibility() {
-        if (mWeatherView != null) {
-            mUiExecutor.execute(() -> {
-                mWeatherView.setVisibility(
-                        mSmartspaceController.isWeatherEnabled() ? View.VISIBLE : View.GONE);
-            });
-        }
-    }
-
-    /**
-     * Sets the clipChildren property on relevant views, to allow the smartspace to draw out of
-     * bounds during the unlock transition.
-     */
-    private void setClipChildrenForUnlock(boolean clip) {
-        if (mStatusArea != null) {
-            mStatusArea.setClipChildren(clip);
-        }
-    }
-
-    @Override
-    public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
-        pw.println("currentClockSizeLarge: " + (mCurrentClockSize == LARGE));
-        pw.println("mCanShowDoubleLineClock: " + mCanShowDoubleLineClock);
-        mView.dump(pw, args);
-        mClockRegistry.dump(pw, args);
-        ClockController clock = getClock();
-        if (clock != null) {
-            clock.dump(pw);
-        }
-        final RegionSampler smallRegionSampler = mClockEventController.getSmallRegionSampler();
-        if (smallRegionSampler != null) {
-            smallRegionSampler.dump(pw);
-        }
-        final RegionSampler largeRegionSampler = mClockEventController.getLargeRegionSampler();
-        if (largeRegionSampler != null) {
-            largeRegionSampler.dump(pw);
-        }
-    }
-
-    /** Returns true if the clock handles the display of weather information */
-    private boolean clockHasCustomWeatherDataDisplay() {
-        ClockController clock = getClock();
-        if (clock == null) {
-            return false;
-        }
-
-        return ((mCurrentClockSize == LARGE) ? clock.getLargeClock() : clock.getSmallClock())
-                .getConfig().getHasCustomWeatherDataDisplay();
-    }
-
-    private void removeViewsFromStatusArea() {
-        for  (int i = mStatusArea.getChildCount() - 1; i >= 0; i--) {
-            final View childView = mStatusArea.getChildAt(i);
-            if (childView.getTag(R.id.tag_smartspace_view) != null) {
-                mStatusArea.removeViewAt(i);
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 1083136..acfa086 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -26,11 +26,9 @@
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
 import android.os.Trace;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.Display;
-import android.view.DisplayAddress;
 import android.view.DisplayInfo;
 import android.view.View;
 import android.view.WindowManager;
@@ -58,6 +56,9 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
+/**
+ * Manages Keyguard Presentations for non-primary display(s).
+ */
 @SysUISingleton
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
@@ -170,14 +171,17 @@
             }
             return false;
         }
-        if (mKeyguardStateController.isOccluded()
-                && mDeviceStateHelper.isConcurrentDisplayActive(display)) {
+
+        final boolean deviceStateOccludesKeyguard =
+                mDeviceStateHelper.isConcurrentDisplayActive(display)
+                        || mDeviceStateHelper.isRearDisplayOuterDefaultActive(display);
+        if (mKeyguardStateController.isOccluded() && deviceStateOccludesKeyguard) {
             if (DEBUG) {
                 // When activities with FLAG_SHOW_WHEN_LOCKED are shown on top of Keyguard, the
                 // Keyguard state becomes "occluded". In this case, we should not show the
                 // KeyguardPresentation, since the activity is presenting content onto the
                 // non-default display.
-                Log.i(TAG, "Do not show KeyguardPresentation when occluded and concurrent"
+                Log.i(TAG, "Do not show KeyguardPresentation when occluded and concurrent or rear"
                         + " display is active");
             }
             return false;
@@ -326,44 +330,45 @@
     public static class DeviceStateHelper implements DeviceStateManager.DeviceStateCallback {
 
         @Nullable
-        private final DisplayAddress.Physical mRearDisplayPhysicalAddress;
-
-        // TODO(b/271317597): These device states should be defined in DeviceStateManager
-        private final int mConcurrentState;
-        private boolean mIsInConcurrentDisplayState;
+        private DeviceState mDeviceState;
 
         @Inject
         DeviceStateHelper(
-                @ShadeDisplayAware Context context,
                 DeviceStateManager deviceStateManager,
                 @Main Executor mainExecutor) {
-
-            final String rearDisplayPhysicalAddress = context.getResources().getString(
-                    com.android.internal.R.string.config_rearDisplayPhysicalAddress);
-            if (TextUtils.isEmpty(rearDisplayPhysicalAddress)) {
-                mRearDisplayPhysicalAddress = null;
-            } else {
-                mRearDisplayPhysicalAddress = DisplayAddress
-                        .fromPhysicalDisplayId(Long.parseLong(rearDisplayPhysicalAddress));
-            }
-
-            mConcurrentState = context.getResources().getInteger(
-                    com.android.internal.R.integer.config_deviceStateConcurrentRearDisplay);
             deviceStateManager.registerCallback(mainExecutor, this);
         }
 
         @Override
         public void onDeviceStateChanged(@NonNull DeviceState state) {
-            // When concurrent state ends, the display also turns off. This is enforced in various
-            // ExtensionRearDisplayPresentationTest CTS tests. So, we don't need to invoke
-            // hide() since that will happen through the onDisplayRemoved callback.
-            mIsInConcurrentDisplayState = state.getIdentifier() == mConcurrentState;
+            // When dual display or rear display mode ends, the display also turns off. This is
+            // enforced in various ExtensionRearDisplayPresentationTest CTS tests. So, we don't need
+            // to invoke hide() since that will happen through the onDisplayRemoved callback.
+            mDeviceState = state;
         }
 
-        boolean isConcurrentDisplayActive(Display display) {
-            return mIsInConcurrentDisplayState
-                    && mRearDisplayPhysicalAddress != null
-                    && mRearDisplayPhysicalAddress.equals(display.getAddress());
+        /**
+         * @return true if the device is in Dual Display mode, and the specified display is the
+         * rear facing (outer) display.
+         */
+        boolean isConcurrentDisplayActive(@NonNull Display display) {
+            return mDeviceState != null
+                    && mDeviceState.hasProperty(
+                            DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT)
+                    && (display.getFlags() & Display.FLAG_REAR) != 0;
+        }
+
+        /**
+         * @return true if the device is the updated Rear Display mode, and the specified display is
+         * the inner display. See {@link DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT}.
+         * Note that in this state, the outer display is the default display, while the inner
+         * display is the "rear" display.
+         */
+        boolean isRearDisplayOuterDefaultActive(@NonNull Display display) {
+            return mDeviceState != null
+                    && mDeviceState.hasProperty(
+                            DeviceState.PROPERTY_FEATURE_REAR_DISPLAY_OUTER_DEFAULT)
+                    && (display.getFlags() & Display.FLAG_REAR) != 0;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
index 63088aa..4246061 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceViewController.java
@@ -22,7 +22,6 @@
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Trace;
-import android.provider.Settings;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
@@ -38,7 +37,6 @@
 import androidx.slice.widget.SliceContent;
 import androidx.slice.widget.SliceLiveData;
 
-import com.android.keyguard.dagger.KeyguardStatusViewScope;
 import com.android.systemui.Dumpable;
 import com.android.systemui.Flags;
 import com.android.systemui.dagger.qualifiers.Background;
@@ -48,7 +46,6 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.ViewController;
 
 import java.io.PrintWriter;
@@ -59,7 +56,6 @@
 import javax.inject.Inject;
 
 /** Controller for a {@link KeyguardSliceView}. */
-@KeyguardStatusViewScope
 public class KeyguardSliceViewController extends ViewController<KeyguardSliceView> implements
         Dumpable {
     private static final String TAG = "KeyguardSliceViewCtrl";
@@ -68,7 +64,6 @@
     private final Handler mBgHandler;
     private final ActivityStarter mActivityStarter;
     private final ConfigurationController mConfigurationController;
-    private final TunerService mTunerService;
     private final DumpManager mDumpManager;
     private final DisplayTracker mDisplayTracker;
     private int mDisplayId;
@@ -77,8 +72,6 @@
     private Slice mSlice;
     private Map<View, PendingIntent> mClickActions;
 
-    TunerService.Tunable mTunable = (key, newValue) -> setupUri(newValue);
-
     ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
         @Override
@@ -116,7 +109,6 @@
             KeyguardSliceView keyguardSliceView,
             ActivityStarter activityStarter,
             ConfigurationController configurationController,
-            TunerService tunerService,
             DumpManager dumpManager,
             DisplayTracker displayTracker) {
         super(keyguardSliceView);
@@ -124,7 +116,6 @@
         mBgHandler = bgHandler;
         mActivityStarter = activityStarter;
         mConfigurationController = configurationController;
-        mTunerService = tunerService;
         mDumpManager = dumpManager;
         mDisplayTracker = displayTracker;
     }
@@ -135,7 +126,6 @@
         if (display != null) {
             mDisplayId = display.getDisplayId();
         }
-        mTunerService.addTunable(mTunable, Settings.Secure.KEYGUARD_SLICE_URI);
         // Make sure we always have the most current slice
         if (mDisplayId == mDisplayTracker.getDefaultDisplayId() && mLiveData != null) {
             mLiveData.observeForever(mObserver);
@@ -153,7 +143,6 @@
         if (mDisplayId == mDisplayTracker.getDefaultDisplayId()) {
             mLiveData.removeObserver(mObserver);
         }
-        mTunerService.removeTunable(mTunable);
         mConfigurationController.removeCallback(mConfigurationListener);
         mDumpManager.unregisterDumpable(
                 TAG + "@" + Integer.toHexString(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt
deleted file mode 100644
index 11b1a7d..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.android.keyguard
-
-import android.content.Context
-import android.util.AttributeSet
-import android.util.FloatProperty
-import android.widget.LinearLayout
-import com.android.systemui.res.R
-import com.android.systemui.statusbar.notification.AnimatableProperty
-
-class KeyguardStatusAreaView(
-    context: Context,
-    attrs: AttributeSet? = null,
-) : LinearLayout(context, attrs) {
-    var translateXFromClockDesign = 0f
-        get() = field
-        set(value) {
-            field = value
-            translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
-        }
-
-    var translateXFromAod = 0f
-        get() = field
-        set(value) {
-            field = value
-            translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
-        }
-
-    var translateXFromUnfold = 0F
-        get() = field
-        set(value) {
-            field = value
-            translationX = translateXFromAod + translateXFromClockDesign + translateXFromUnfold
-        }
-
-    var translateYFromClockSize = 0f
-        get() = field
-        set(value) {
-            field = value
-            translationY = value + translateYFromClockDesign
-        }
-
-    var translateYFromClockDesign = 0f
-        get() = field
-        set(value) {
-            field = value
-            translationY = value + translateYFromClockSize
-        }
-
-    companion object {
-        @JvmField
-        val TRANSLATE_X_CLOCK_DESIGN =
-            AnimatableProperty.from(
-                object : FloatProperty<KeyguardStatusAreaView>("TranslateXClockDesign") {
-                    override fun setValue(view: KeyguardStatusAreaView, value: Float) {
-                        view.translateXFromClockDesign = value
-                    }
-
-                    override fun get(view: KeyguardStatusAreaView): Float {
-                        return view.translateXFromClockDesign
-                    }
-                },
-                R.id.translate_x_clock_design_animator_tag,
-                R.id.translate_x_clock_design_animator_start_tag,
-                R.id.translate_x_clock_design_animator_end_tag
-            )
-
-        @JvmField
-        val TRANSLATE_X_AOD =
-            AnimatableProperty.from(
-                object : FloatProperty<KeyguardStatusAreaView>("TranslateXAod") {
-                    override fun setValue(view: KeyguardStatusAreaView, value: Float) {
-                        view.translateXFromAod = value
-                    }
-
-                    override fun get(view: KeyguardStatusAreaView): Float {
-                        return view.translateXFromAod
-                    }
-                },
-                R.id.translate_x_aod_animator_tag,
-                R.id.translate_x_aod_animator_start_tag,
-                R.id.translate_x_aod_animator_end_tag
-            )
-
-        @JvmField
-        val TRANSLATE_Y_CLOCK_SIZE =
-            AnimatableProperty.from(
-                object : FloatProperty<KeyguardStatusAreaView>("TranslateYClockSize") {
-                    override fun setValue(view: KeyguardStatusAreaView, value: Float) {
-                        view.translateYFromClockSize = value
-                    }
-
-                    override fun get(view: KeyguardStatusAreaView): Float {
-                        return view.translateYFromClockSize
-                    }
-                },
-                R.id.translate_y_clock_size_animator_tag,
-                R.id.translate_y_clock_size_animator_start_tag,
-                R.id.translate_y_clock_size_animator_end_tag
-            )
-
-        @JvmField
-        val TRANSLATE_Y_CLOCK_DESIGN =
-            AnimatableProperty.from(
-                object : FloatProperty<KeyguardStatusAreaView>("TranslateYClockDesign") {
-                    override fun setValue(view: KeyguardStatusAreaView, value: Float) {
-                        view.translateYFromClockDesign = value
-                    }
-
-                    override fun get(view: KeyguardStatusAreaView): Float {
-                        return view.translateYFromClockDesign
-                    }
-                },
-                R.id.translate_y_clock_design_animator_tag,
-                R.id.translate_y_clock_design_animator_start_tag,
-                R.id.translate_y_clock_design_animator_end_tag
-            )
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusContainer.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusContainer.kt
deleted file mode 100644
index 298eff2..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusContainer.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.keyguard
-
-import android.content.Context
-import android.graphics.Canvas
-import android.util.AttributeSet
-import android.widget.LinearLayout
-
-class KeyguardStatusContainer(
-    context: Context,
-    attrs: AttributeSet,
-) : LinearLayout(context, attrs) {
-    private var drawAlpha: Int = 255
-
-    protected override fun onSetAlpha(alpha: Int): Boolean {
-        drawAlpha = alpha
-        return true
-    }
-
-    protected override fun dispatchDraw(canvas: Canvas) {
-        KeyguardClockFrame.saveCanvasAlpha(this, canvas, drawAlpha) { super.dispatchDraw(canvas) }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
deleted file mode 100644
index 073f33fe..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static java.util.Collections.emptySet;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.os.Build;
-import android.os.Trace;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
-import android.widget.GridLayout;
-
-import com.android.systemui.res.R;
-import com.android.systemui.shade.TouchLogger;
-import com.android.systemui.statusbar.CrossFadeHelper;
-
-import java.util.Set;
-
-/**
- * View consisting of:
- * - keyguard clock
- * - media player (split shade mode only)
- */
-public class KeyguardStatusView extends GridLayout {
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-    private static final String TAG = "KeyguardStatusView";
-
-    private ViewGroup mStatusViewContainer;
-    private KeyguardClockSwitch mClockView;
-    private KeyguardSliceView mKeyguardSlice;
-    private View mMediaHostContainer;
-
-    private int mDrawAlpha = 255;
-    private float mDarkAmount = 0;
-
-    public KeyguardStatusView(Context context) {
-        this(context, null, 0);
-    }
-
-    public KeyguardStatusView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public KeyguardStatusView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mStatusViewContainer = findViewById(R.id.status_view_container);
-
-        mClockView = findViewById(R.id.keyguard_clock_container);
-        if (KeyguardClockAccessibilityDelegate.isNeeded(mContext)) {
-            mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
-        }
-
-        mKeyguardSlice = findViewById(R.id.keyguard_slice_view);
-
-        mMediaHostContainer = findViewById(R.id.status_view_media_container);
-
-        updateDark();
-    }
-
-    void setDarkAmount(float darkAmount) {
-        if (mDarkAmount == darkAmount) {
-            return;
-        }
-        mDarkAmount = darkAmount;
-        CrossFadeHelper.fadeOut(mMediaHostContainer, darkAmount);
-        updateDark();
-    }
-
-    void updateDark() {
-        mKeyguardSlice.setDarkAmount(mDarkAmount);
-    }
-
-    /** Sets a translationY value on every child view except for the media view. */
-    public void setChildrenTranslationY(float translationY, boolean excludeMedia) {
-        setChildrenTranslationYExcluding(translationY,
-                excludeMedia ? Set.of(mMediaHostContainer) : emptySet());
-    }
-
-    /** Sets a translationY value on every view except for the views in the provided set. */
-    private void setChildrenTranslationYExcluding(float translationY, Set<View> excludedViews) {
-        for (int i = 0; i < mStatusViewContainer.getChildCount(); i++) {
-            final View child = mStatusViewContainer.getChildAt(i);
-
-            if (!excludedViews.contains(child)) {
-                child.setTranslationY(translationY);
-            }
-        }
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev));
-    }
-
-    @Override
-    public ViewPropertyAnimator animate() {
-        if (Build.IS_DEBUGGABLE) {
-            throw new IllegalArgumentException(
-                    "KeyguardStatusView does not support ViewPropertyAnimator. "
-                            + "Use PropertyAnimator instead.");
-        }
-        return super.animate();
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        Trace.beginSection("KeyguardStatusView#onMeasure");
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        Trace.endSection();
-    }
-
-    @Override
-    protected boolean onSetAlpha(int alpha) {
-        mDrawAlpha = alpha;
-        return true;
-    }
-
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        KeyguardClockFrame.saveCanvasAlpha(
-                this, canvas, mDrawAlpha,
-                c -> {
-                    super.dispatchDraw(c);
-                    return kotlin.Unit.INSTANCE;
-                });
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
deleted file mode 100644
index 0684824..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ /dev/null
@@ -1,664 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static androidx.constraintlayout.widget.ConstraintSet.END;
-import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
-
-import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
-import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
-
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.annotation.Nullable;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.transition.ChangeBounds;
-import android.transition.Transition;
-import android.transition.TransitionListenerAdapter;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.transition.TransitionValues;
-import android.util.Slog;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.constraintlayout.widget.ConstraintLayout;
-import androidx.constraintlayout.widget.ConstraintSet;
-import androidx.viewpager.widget.ViewPager;
-
-import com.android.app.animation.Interpolators;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.keyguard.KeyguardClockSwitch.ClockSize;
-import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.animation.ViewHierarchyAnimator;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.plugins.clocks.ClockController;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
-import com.android.systemui.power.shared.model.ScreenPowerState;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.ViewController;
-
-import kotlin.coroutines.CoroutineContext;
-import kotlin.coroutines.EmptyCoroutineContext;
-
-import javax.inject.Inject;
-
-/**
- * Injectable controller for {@link KeyguardStatusView}.
- */
-public class KeyguardStatusViewController extends ViewController<KeyguardStatusView> {
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-    @VisibleForTesting static final String TAG = "KeyguardStatusViewController";
-    private static final long STATUS_AREA_HEIGHT_ANIMATION_MILLIS = 133;
-
-    /**
-     * Duration to use for the animator when the keyguard status view alignment changes, and a
-     * custom clock animation is in use.
-     */
-    private static final int KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION = 1000;
-
-    public static final AnimationProperties CLOCK_ANIMATION_PROPERTIES =
-            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-
-    private final KeyguardSliceViewController mKeyguardSliceViewController;
-    private final KeyguardClockSwitchController mKeyguardClockSwitchController;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final ConfigurationController mConfigurationController;
-    private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
-    private final InteractionJankMonitor mInteractionJankMonitor;
-    private final Rect mClipBounds = new Rect();
-    private final KeyguardInteractor mKeyguardInteractor;
-    private final PowerInteractor mPowerInteractor;
-    private final DozeParameters mDozeParameters;
-
-    private View mStatusArea = null;
-    private ValueAnimator mStatusAreaHeightAnimator = null;
-
-    private Boolean mSplitShadeEnabled = false;
-    private Boolean mStatusViewCentered = true;
-
-    private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
-            new TransitionListenerAdapter() {
-                @Override
-                public void onTransitionCancel(Transition transition) {
-                    mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
-                }
-
-                @Override
-                public void onTransitionEnd(Transition transition) {
-                    mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
-                }
-            };
-
-    private final View.OnLayoutChangeListener mStatusAreaLayoutChangeListener =
-            new View.OnLayoutChangeListener() {
-                @Override
-                public void onLayoutChange(View v,
-                        int left, int top, int right, int bottom,
-                        int oldLeft, int oldTop, int oldRight, int oldBottom
-                ) {
-                    if (!mDozeParameters.getAlwaysOn()) {
-                        return;
-                    }
-
-                    int oldHeight = oldBottom - oldTop;
-                    int diff = v.getHeight() - oldHeight;
-                    if (diff == 0) {
-                        return;
-                    }
-
-                    int startValue = -1 * diff;
-                    long duration = STATUS_AREA_HEIGHT_ANIMATION_MILLIS;
-                    if (mStatusAreaHeightAnimator != null
-                            && mStatusAreaHeightAnimator.isRunning()) {
-                        duration += mStatusAreaHeightAnimator.getDuration()
-                                - mStatusAreaHeightAnimator.getCurrentPlayTime();
-                        startValue += (int) mStatusAreaHeightAnimator.getAnimatedValue();
-                        mStatusAreaHeightAnimator.cancel();
-                        mStatusAreaHeightAnimator = null;
-                    }
-
-                    mStatusAreaHeightAnimator = ValueAnimator.ofInt(startValue, 0);
-                    mStatusAreaHeightAnimator.setDuration(duration);
-                    final View nic = mKeyguardClockSwitchController.getAodNotifIconContainer();
-                    if (nic != null) {
-                        mStatusAreaHeightAnimator.addUpdateListener(anim -> {
-                            nic.setTranslationY((int) anim.getAnimatedValue());
-                        });
-                    }
-                    mStatusAreaHeightAnimator.start();
-                }
-            };
-
-    @Inject
-    public KeyguardStatusViewController(
-            KeyguardStatusView keyguardStatusView,
-            KeyguardSliceViewController keyguardSliceViewController,
-            KeyguardClockSwitchController keyguardClockSwitchController,
-            KeyguardStateController keyguardStateController,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            ConfigurationController configurationController,
-            DozeParameters dozeParameters,
-            ScreenOffAnimationController screenOffAnimationController,
-            KeyguardLogger logger,
-            InteractionJankMonitor interactionJankMonitor,
-            KeyguardInteractor keyguardInteractor,
-            PowerInteractor powerInteractor) {
-        super(keyguardStatusView);
-        mKeyguardSliceViewController = keyguardSliceViewController;
-        mKeyguardClockSwitchController = keyguardClockSwitchController;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mConfigurationController = configurationController;
-        mDozeParameters = dozeParameters;
-        mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
-                dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
-                logger.getBuffer());
-        mInteractionJankMonitor = interactionJankMonitor;
-        mKeyguardInteractor = keyguardInteractor;
-        mPowerInteractor = powerInteractor;
-    }
-
-    @Override
-    public void onInit() {
-        mKeyguardClockSwitchController.init();
-        final View mediaHostContainer = mView.findViewById(R.id.status_view_media_container);
-        if (mediaHostContainer != null) {
-            mKeyguardClockSwitchController.getView().addOnLayoutChangeListener(
-                    (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                        if (!mSplitShadeEnabled
-                                || mKeyguardClockSwitchController.getView().getSplitShadeCentered()
-                                // Note: isKeyguardVisible() returns false after Launcher -> AOD.
-                                || !mKeyguardUpdateMonitor.isKeyguardVisible()) {
-                            return;
-                        }
-
-                        int oldHeight = oldBottom - oldTop;
-                        if (v.getHeight() == oldHeight) return;
-
-                        if (mediaHostContainer.getVisibility() != View.VISIBLE
-                                // If the media is appearing, also don't do the transition.
-                                || mediaHostContainer.getHeight() == 0) {
-                            return;
-                        }
-
-                        ViewHierarchyAnimator.Companion.animateNextUpdate(mediaHostContainer,
-                                Interpolators.STANDARD, /* duration= */ 500L,
-                                /* animateChildren= */ false);
-                    });
-        }
-
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            startCoroutines(EmptyCoroutineContext.INSTANCE);
-            mView.setVisibility(View.GONE);
-        }
-    }
-
-    void startCoroutines(CoroutineContext context) {
-        collectFlow(mView, mKeyguardInteractor.getDozeTimeTick(),
-                (Long millis) -> {
-                        dozeTimeTick();
-                }, context);
-
-        collectFlow(mView, mPowerInteractor.getScreenPowerState(),
-                (ScreenPowerState powerState) -> {
-                    if (powerState == ScreenPowerState.SCREEN_TURNING_ON) {
-                        dozeTimeTick();
-                    }
-                }, context);
-    }
-
-    public KeyguardStatusView getView() {
-        return mView;
-    }
-
-    @Override
-    protected void onViewAttached() {
-        mStatusArea = mView.findViewById(R.id.keyguard_status_area);
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-
-        mStatusArea.addOnLayoutChangeListener(mStatusAreaLayoutChangeListener);
-        mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
-        mConfigurationController.addCallback(mConfigurationListener);
-    }
-
-    @Override
-    protected void onViewDetached() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-
-        mStatusArea.removeOnLayoutChangeListener(mStatusAreaLayoutChangeListener);
-        mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
-        mConfigurationController.removeCallback(mConfigurationListener);
-    }
-
-    /** Sets the StatusView as shown on an external display. */
-    public void setDisplayedOnSecondaryDisplay() {
-        mKeyguardClockSwitchController.setShownOnSecondaryDisplay(true);
-    }
-
-    /**
-     * Updates views on doze time tick.
-     */
-    public void dozeTimeTick() {
-        refreshTime();
-        mKeyguardSliceViewController.refresh();
-    }
-
-    /**
-     * Set which clock should be displayed on the keyguard. The other one will be automatically
-     * hidden.
-     */
-    public void displayClock(@ClockSize int clockSize, boolean animate) {
-        mKeyguardClockSwitchController.displayClock(clockSize, animate);
-    }
-
-    /**
-     * Performs fold to aod animation of the clocks (changes font weight from bold to thin).
-     * This animation is played when AOD is enabled and foldable device is fully folded, it is
-     * displayed on the outer screen
-     * @param foldFraction current fraction of fold animation complete
-     */
-    public void animateFoldToAod(float foldFraction) {
-        mKeyguardClockSwitchController.animateFoldToAod(foldFraction);
-    }
-
-    /**
-     * Sets a translationY on the views on the keyguard, except on the media view.
-     */
-    public void setTranslationY(float translationY, boolean excludeMedia) {
-        mView.setChildrenTranslationY(translationY, excludeMedia);
-    }
-
-    /**
-     * Set keyguard status view alpha.
-     */
-    public void setAlpha(float alpha) {
-        if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
-            mView.setAlpha(alpha);
-        }
-    }
-
-    /**
-     * Update the pivot position based on the parent view
-     */
-    public void updatePivot(float parentWidth, float parentHeight) {
-        mView.setPivotX(parentWidth / 2f);
-        mView.setPivotY(mKeyguardClockSwitchController.getClockHeight() / 2f);
-    }
-
-    /**
-     * Get the height of the keyguard status view without the notification icon area, as that's
-     * only visible on AOD.
-     *
-     * We internally animate height changes to the status area to prevent discontinuities in the
-     * doze animation introduced by the height suddenly changing due to smartpace.
-     */
-    public int getLockscreenHeight() {
-        int heightAnimValue = mStatusAreaHeightAnimator == null ? 0 :
-                (int) mStatusAreaHeightAnimator.getAnimatedValue();
-        return mView.getHeight() + heightAnimValue
-                - mKeyguardClockSwitchController.getNotificationIconAreaHeight();
-    }
-
-    /**
-     * Get y-bottom position of the currently visible clock.
-     */
-    public int getClockBottom(int statusBarHeaderHeight) {
-        return mKeyguardClockSwitchController.getClockBottom(statusBarHeaderHeight);
-    }
-
-    /**
-     * @return true if the currently displayed clock is top aligned (as opposed to center aligned)
-     */
-    public boolean isClockTopAligned() {
-        return mKeyguardClockSwitchController.isClockTopAligned();
-    }
-
-    /**
-     * Pass top margin from ClockPositionAlgorithm in NotificationPanelViewController
-     * Use for clock view in LS to compensate for top margin to align to the screen
-     * Regardless of translation from AOD and unlock gestures
-     */
-    public void setLockscreenClockY(int clockY) {
-        mKeyguardClockSwitchController.setLockscreenClockY(clockY);
-    }
-
-    /**
-     * Set whether the view accessibility importance mode.
-     */
-    public void setStatusAccessibilityImportance(int mode) {
-        mView.setImportantForAccessibility(mode);
-    }
-
-    @VisibleForTesting
-    void setProperty(AnimatableProperty property, float value, boolean animate) {
-        PropertyAnimator.setProperty(mView, property, value, CLOCK_ANIMATION_PROPERTIES, animate);
-    }
-
-    /**
-     * Update position of the view with an optional animation
-     */
-    public void updatePosition(int x, int y, float scale, boolean animate) {
-        setProperty(AnimatableProperty.Y, y, animate);
-
-        ClockController clock = mKeyguardClockSwitchController.getClock();
-        if (clock != null && clock.getConfig().getUseAlternateSmartspaceAODTransition()) {
-            // If requested, scale the entire view instead of just the clock view
-            mKeyguardClockSwitchController.updatePosition(x, 1f /* scale */,
-                    CLOCK_ANIMATION_PROPERTIES, animate);
-            setProperty(AnimatableProperty.SCALE_X, scale, animate);
-            setProperty(AnimatableProperty.SCALE_Y, scale, animate);
-        } else {
-            mKeyguardClockSwitchController.updatePosition(x, scale,
-                    CLOCK_ANIMATION_PROPERTIES, animate);
-            setProperty(AnimatableProperty.SCALE_X, 1f, animate);
-            setProperty(AnimatableProperty.SCALE_Y, 1f, animate);
-        }
-    }
-
-    /**
-     * Set the visibility of the keyguard status view based on some new state.
-     */
-    public void setKeyguardStatusViewVisibility(
-            int statusBarState,
-            boolean keyguardFadingAway,
-            boolean goingToFullShade,
-            int oldStatusBarState) {
-        mKeyguardVisibilityHelper.setViewVisibility(
-                statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
-    }
-
-    private void refreshTime() {
-        mKeyguardClockSwitchController.refresh();
-    }
-
-    private final ConfigurationController.ConfigurationListener mConfigurationListener =
-            new ConfigurationController.ConfigurationListener() {
-        @Override
-        public void onLocaleListChanged() {
-            refreshTime();
-            mKeyguardClockSwitchController.onLocaleListChanged();
-        }
-
-        @Override
-        public void onConfigChanged(Configuration newConfig) {
-            mKeyguardClockSwitchController.onConfigChanged();
-        }
-    };
-
-    private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onTimeChanged() {
-            Slog.v(TAG, "onTimeChanged");
-            refreshTime();
-        }
-
-        @Override
-        public void onKeyguardVisibilityChanged(boolean visible) {
-            if (visible) {
-                if (DEBUG) Slog.v(TAG, "refresh statusview visible:true");
-                refreshTime();
-            }
-        }
-    };
-
-    /**
-     * Rect that specifies how KSV should be clipped, on its parent's coordinates.
-     */
-    public void setClipBounds(Rect clipBounds) {
-        if (clipBounds != null) {
-            mClipBounds.set(clipBounds.left, (int) (clipBounds.top - mView.getY()),
-                    clipBounds.right, (int) (clipBounds.bottom - mView.getY()));
-            mView.setClipBounds(mClipBounds);
-        } else {
-            mView.setClipBounds(null);
-        }
-    }
-
-    /**
-     * Returns true if the large clock will block the notification shelf in AOD
-     */
-    public boolean isLargeClockBlockingNotificationShelf() {
-        ClockController clock = mKeyguardClockSwitchController.getClock();
-        return clock != null && clock.getLargeClock().getConfig().getHasCustomWeatherDataDisplay();
-    }
-
-    /**
-     * Set if the split shade is enabled
-     */
-    public void setSplitShadeEnabled(boolean enabled) {
-        mKeyguardClockSwitchController.setSplitShadeEnabled(enabled);
-        mSplitShadeEnabled = enabled;
-    }
-
-    /**
-     * Updates the alignment of the KeyguardStatusView and animates the transition if requested.
-     */
-    public void updateAlignment(
-            ConstraintLayout layout,
-            boolean splitShadeEnabled,
-            boolean shouldBeCentered,
-            boolean animate) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardInteractor.setClockShouldBeCentered(shouldBeCentered);
-        } else {
-            mKeyguardClockSwitchController.setSplitShadeCentered(
-                    splitShadeEnabled && shouldBeCentered);
-        }
-        if (mStatusViewCentered == shouldBeCentered) {
-            return;
-        }
-
-        mStatusViewCentered = shouldBeCentered;
-        if (layout == null) {
-            return;
-        }
-
-        ConstraintSet constraintSet = new ConstraintSet();
-        constraintSet.clone(layout);
-        int guideline;
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            guideline = R.id.split_shade_guideline;
-        } else {
-            guideline = R.id.qs_edge_guideline;
-        }
-
-        int statusConstraint = shouldBeCentered ? PARENT_ID : guideline;
-        constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
-        if (!animate) {
-            constraintSet.applyTo(layout);
-            return;
-        }
-
-        mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
-        /* This transition blocks any layout changes while running. For that reason
-        * special logic with setting visibility was added to {@link BcSmartspaceView#setDozing}
-        * for split shade to avoid jump of the media object. */
-        ChangeBounds transition = new ChangeBounds();
-        if (splitShadeEnabled) {
-            // Excluding media from the transition on split-shade, as it doesn't transition
-            // horizontally properly.
-            transition.excludeTarget(R.id.status_view_media_container, true);
-
-            // Exclude smartspace viewpager and its children from the transition.
-            //     - Each step of the transition causes the ViewPager to invoke resize,
-            //     which invokes scrolling to the recalculated position. The scrolling
-            //     actions are congested, resulting in kinky translation, and
-            //     delay in settling to the final position. (http://b/281620564#comment1)
-            //     - Also, the scrolling is unnecessary in the transition. We just want
-            //     the viewpager to stay on the same page.
-            //     - Exclude by Class type instead of resource id, since the resource id
-            //     isn't available for all devices, and probably better to exclude all
-            //     ViewPagers any way.
-            transition.excludeTarget(ViewPager.class, true);
-            transition.excludeChildren(ViewPager.class, true);
-        }
-
-        transition.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        transition.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-
-        ClockController clock = mKeyguardClockSwitchController.getClock();
-        boolean customClockAnimation = clock != null
-                && clock.getLargeClock().getConfig().getHasCustomPositionUpdatedAnimation();
-        // When migrateClocksToBlueprint is on, customized clock animation is conducted in
-        // KeyguardClockViewBinder
-        if (customClockAnimation && !MigrateClocksToBlueprint.isEnabled()) {
-            // Find the clock, so we can exclude it from this transition.
-            FrameLayout clockContainerView = mView.findViewById(
-                    com.android.systemui.customization.R.id.lockscreen_clock_view_large);
-
-            // The clock container can sometimes be null. If it is, just fall back to the
-            // old animation rather than setting up the custom animations.
-            if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
-                transition.addListener(mKeyguardStatusAlignmentTransitionListener);
-                TransitionManager.beginDelayedTransition(layout, transition);
-            } else {
-                View clockView = clockContainerView.getChildAt(0);
-
-                TransitionSet set = new TransitionSet();
-                set.addTransition(transition);
-
-                SplitShadeTransitionAdapter adapter =
-                        new SplitShadeTransitionAdapter(mKeyguardClockSwitchController);
-
-                // Use linear here, so the actual clock can pick its own interpolator.
-                adapter.setInterpolator(Interpolators.LINEAR);
-                adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
-                adapter.addTarget(clockView);
-                set.addTransition(adapter);
-
-                if (splitShadeEnabled) {
-                    // Exclude smartspace viewpager and its children from the transition set.
-                    //     - This is necessary in addition to excluding them from the
-                    //     ChangeBounds child transition.
-                    //     - Without this, the viewpager is scrolled to the new position
-                    //     (corresponding to its end size) before the size change is realized.
-                    //     Note that the size change is realized at the end of the ChangeBounds
-                    //     transition. With the "prescrolling", the viewpager ends up in a weird
-                    //     position, then recovers smoothly during the transition, and ends at
-                    //     the position for the current page.
-                    //     - Exclude by Class type instead of resource id, since the resource id
-                    //     isn't available for all devices, and probably better to exclude all
-                    //     ViewPagers any way.
-                    set.excludeTarget(ViewPager.class, true);
-                    set.excludeChildren(ViewPager.class, true);
-                }
-
-                set.addListener(mKeyguardStatusAlignmentTransitionListener);
-                TransitionManager.beginDelayedTransition(layout, set);
-            }
-        } else {
-            transition.addListener(mKeyguardStatusAlignmentTransitionListener);
-            TransitionManager.beginDelayedTransition(layout, transition);
-        }
-
-        constraintSet.applyTo(layout);
-    }
-
-    public ClockController getClockController() {
-        return mKeyguardClockSwitchController.getClock();
-    }
-
-    String getInstanceName() {
-        return TAG + "#" + hashCode();
-    }
-
-    @VisibleForTesting
-    static class SplitShadeTransitionAdapter extends Transition {
-        private static final String PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft";
-        private static final String PROP_BOUNDS_RIGHT = "splitShadeTransitionAdapter:boundsRight";
-        private static final String PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow";
-        private static final String[] TRANSITION_PROPERTIES = {
-                PROP_BOUNDS_LEFT, PROP_BOUNDS_RIGHT, PROP_X_IN_WINDOW};
-
-        private final KeyguardClockSwitchController mController;
-
-        @VisibleForTesting
-        SplitShadeTransitionAdapter(KeyguardClockSwitchController controller) {
-            mController = controller;
-        }
-
-        private void captureValues(TransitionValues transitionValues) {
-            transitionValues.values.put(PROP_BOUNDS_LEFT, transitionValues.view.getLeft());
-            transitionValues.values.put(PROP_BOUNDS_RIGHT, transitionValues.view.getRight());
-            int[] locationInWindowTmp = new int[2];
-            transitionValues.view.getLocationInWindow(locationInWindowTmp);
-            transitionValues.values.put(PROP_X_IN_WINDOW, locationInWindowTmp[0]);
-        }
-
-        @Override
-        public void captureEndValues(TransitionValues transitionValues) {
-            captureValues(transitionValues);
-        }
-
-        @Override
-        public void captureStartValues(TransitionValues transitionValues) {
-            captureValues(transitionValues);
-        }
-
-        @Nullable
-        @Override
-        public Animator createAnimator(@NonNull ViewGroup sceneRoot,
-                @Nullable TransitionValues startValues,
-                @Nullable TransitionValues endValues) {
-            if (startValues == null || endValues == null) {
-                return null;
-            }
-            ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
-
-            int fromLeft = (int) startValues.values.get(PROP_BOUNDS_LEFT);
-            int fromWindowX = (int) startValues.values.get(PROP_X_IN_WINDOW);
-            int toWindowX = (int) endValues.values.get(PROP_X_IN_WINDOW);
-            // Using windowX, to determine direction, instead of left, as in RTL the difference of
-            // toLeft - fromLeft is always positive, even when moving left.
-            int direction = toWindowX - fromWindowX > 0 ? 1 : -1;
-
-            anim.addUpdateListener(animation -> {
-                ClockController clock = mController.getClock();
-                if (clock == null) {
-                    return;
-                }
-
-                clock.getLargeClock().getAnimations()
-                        .onPositionUpdated(fromLeft, direction, animation.getAnimatedFraction());
-            });
-
-            return anim;
-        }
-
-        @Override
-        public String[] getTransitionProperties() {
-            return TRANSITION_PROPERTIES;
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
index 07bd813..40a86dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
@@ -19,13 +19,12 @@
 import android.content.Context
 import android.view.View
 import com.android.systemui.customization.R as customR
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.ui.view.KeyguardRootView
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.res.R
-import com.android.systemui.shared.R as sharedR
 import com.android.systemui.shade.NotificationShadeWindowView
 import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shared.R as sharedR
 import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator
 import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.END
 import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction.START
@@ -55,16 +54,17 @@
     var statusViewCentered = false
 
     private val filterKeyguardAndSplitShadeOnly: () -> Boolean = {
-        statusBarStateController.getState() == KEYGUARD && !statusViewCentered }
+        statusBarStateController.getState() == KEYGUARD && !statusViewCentered
+    }
     private val filterKeyguard: () -> Boolean = { statusBarStateController.getState() == KEYGUARD }
 
     private val translateAnimator by lazy {
-        val smartSpaceViews = if (MigrateClocksToBlueprint.isEnabled) {
-            // Use scrollX instead of translationX as translation is already set by [AodBurnInLayer]
-            val scrollXTranslation = { view: View, translation: Float ->
-                view.scrollX = -translation.toInt()
-            }
+        // Use scrollX instead of translationX as translation is already set by [AodBurnInLayer]
+        val scrollXTranslation = { view: View, translation: Float ->
+            view.scrollX = -translation.toInt()
+        }
 
+        val smartSpaceViews =
             setOf(
                 ViewIdToTranslate(
                     viewId = sharedR.id.date_smartspace_view,
@@ -83,18 +83,8 @@
                     direction = START,
                     shouldBeAnimated = filterKeyguard,
                     translateFunc = scrollXTranslation,
-                )
+                ),
             )
-        } else {
-            setOf(ViewIdToTranslate(
-                viewId = R.id.keyguard_status_area,
-                direction = START,
-                shouldBeAnimated = filterKeyguard,
-                translateFunc = { view, value ->
-                    (view as? KeyguardStatusAreaView)?.translateXFromUnfold = value
-                }
-            ))
-        }
 
         UnfoldConstantTranslateAnimator(
             viewsIdToTranslate =
@@ -102,39 +92,39 @@
                     ViewIdToTranslate(
                         viewId = customR.id.lockscreen_clock_view_large,
                         direction = START,
-                        shouldBeAnimated = filterKeyguardAndSplitShadeOnly
+                        shouldBeAnimated = filterKeyguardAndSplitShadeOnly,
                     ),
                     ViewIdToTranslate(
                         viewId = customR.id.lockscreen_clock_view,
                         direction = START,
-                        shouldBeAnimated = filterKeyguard
+                        shouldBeAnimated = filterKeyguard,
                     ),
                     ViewIdToTranslate(
                         viewId = R.id.notification_stack_scroller,
                         direction = END,
-                        shouldBeAnimated = filterKeyguardAndSplitShadeOnly
-                    )
+                        shouldBeAnimated = filterKeyguardAndSplitShadeOnly,
+                    ),
                 ) + smartSpaceViews,
-            progressProvider = unfoldProgressProvider
+            progressProvider = unfoldProgressProvider,
         )
     }
 
     private val shortcutButtonsAnimator by lazy {
         UnfoldConstantTranslateAnimator(
             viewsIdToTranslate =
-            setOf(
-                ViewIdToTranslate(
-                    viewId = R.id.start_button,
-                    direction = START,
-                    shouldBeAnimated = filterKeyguard
+                setOf(
+                    ViewIdToTranslate(
+                        viewId = R.id.start_button,
+                        direction = START,
+                        shouldBeAnimated = filterKeyguard,
+                    ),
+                    ViewIdToTranslate(
+                        viewId = R.id.end_button,
+                        direction = END,
+                        shouldBeAnimated = filterKeyguard,
+                    ),
                 ),
-                ViewIdToTranslate(
-                    viewId = R.id.end_button,
-                    direction = END,
-                    shouldBeAnimated = filterKeyguard
-                )
-            ),
-            progressProvider = unfoldProgressProvider
+            progressProvider = unfoldProgressProvider,
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
deleted file mode 100644
index fd8b6d5..0000000
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
-import static com.android.systemui.statusbar.StatusBarState.SHADE;
-
-import android.util.Property;
-import android.view.View;
-
-import com.android.app.animation.Interpolators;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
-import com.android.systemui.log.LogBuffer;
-import com.android.systemui.log.core.LogLevel;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.Assert;
-
-import com.google.errorprone.annotations.CompileTimeConstant;
-
-import java.util.function.Consumer;
-
-/**
- * Helper class for updating visibility of keyguard views based on keyguard and status bar state.
- * This logic is shared by both the keyguard status view and the keyguard user switcher.
- */
-public class KeyguardVisibilityHelper {
-    private static final String TAG = "KeyguardVisibilityHelper";
-
-    private View mView;
-    private final KeyguardStateController mKeyguardStateController;
-    private final DozeParameters mDozeParameters;
-    private final ScreenOffAnimationController mScreenOffAnimationController;
-    private boolean mAnimateYPos;
-    private boolean mKeyguardViewVisibilityAnimating;
-    private boolean mLastOccludedState = false;
-    private final AnimationProperties mAnimationProperties = new AnimationProperties();
-    private final LogBuffer mLogBuffer;
-
-    public KeyguardVisibilityHelper(View view,
-            KeyguardStateController keyguardStateController,
-            DozeParameters dozeParameters,
-            ScreenOffAnimationController screenOffAnimationController,
-            boolean animateYPos,
-            LogBuffer logBuffer) {
-        mView = view;
-        mKeyguardStateController = keyguardStateController;
-        mDozeParameters = dozeParameters;
-        mScreenOffAnimationController = screenOffAnimationController;
-        mAnimateYPos = animateYPos;
-        mLogBuffer = logBuffer;
-    }
-
-    private void log(@CompileTimeConstant String message) {
-        if (mLogBuffer != null) {
-            mLogBuffer.log(TAG, LogLevel.DEBUG, message);
-        }
-    }
-
-    public boolean isVisibilityAnimating() {
-        return mKeyguardViewVisibilityAnimating;
-    }
-
-    /**
-     * Set the visibility of a keyguard view based on some new state.
-     */
-    public void setViewVisibility(
-            int statusBarState,
-            boolean keyguardFadingAway,
-            boolean goingToFullShade,
-            int oldStatusBarState) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            log("Ignoring KeyguardVisibilityelper, migrateClocksToBlueprint flag on");
-            return;
-        }
-        Assert.isMainThread();
-        PropertyAnimator.cancelAnimation(mView, AnimatableProperty.ALPHA);
-        boolean isOccluded = mKeyguardStateController.isOccluded();
-        mKeyguardViewVisibilityAnimating = false;
-
-        if ((!keyguardFadingAway && oldStatusBarState == KEYGUARD
-                && statusBarState != KEYGUARD) || goingToFullShade) {
-            mKeyguardViewVisibilityAnimating = true;
-
-            AnimationProperties animProps = new AnimationProperties()
-                    .setCustomInterpolator(View.ALPHA, Interpolators.ALPHA_OUT)
-                    .setAnimationEndAction(mSetGoneEndAction);
-            if (keyguardFadingAway) {
-                animProps
-                        .setDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
-                        .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration());
-                log("goingToFullShade && keyguardFadingAway");
-            } else {
-                animProps.setDelay(0).setDuration(160);
-                log("goingToFullShade && !keyguardFadingAway");
-            }
-            if (MigrateClocksToBlueprint.isEnabled()) {
-                log("Using LockscreenToGoneTransition 1");
-            } else {
-                PropertyAnimator.setProperty(
-                        mView, AnimatableProperty.ALPHA, 0f, animProps, true /* animate */);
-            }
-        } else if (oldStatusBarState == StatusBarState.SHADE_LOCKED && statusBarState == KEYGUARD) {
-            mView.setVisibility(View.VISIBLE);
-            mKeyguardViewVisibilityAnimating = true;
-            mView.setAlpha(0f);
-            PropertyAnimator.setProperty(
-                    mView, AnimatableProperty.ALPHA, 1f,
-                    new AnimationProperties()
-                            .setDelay(0)
-                            .setDuration(320)
-                            .setCustomInterpolator(View.ALPHA, Interpolators.ALPHA_IN)
-                            .setAnimationEndAction(
-                                    property -> mSetVisibleEndRunnable.run()),
-                    true /* animate */);
-            log("keyguardFadingAway transition w/ Y Aniamtion");
-        } else if (statusBarState == KEYGUARD) {
-            // Sometimes, device will be unlocked and then locked very quickly.
-            // keyguardFadingAway hasn't been set to false cause unlock animation hasn't finished
-            // So we should not animate keyguard fading away in this case (when oldState is SHADE)
-            if (oldStatusBarState != SHADE) {
-                log("statusBarState == KEYGUARD && oldStatusBarState != SHADE");
-            } else {
-                log("statusBarState == KEYGUARD && oldStatusBarState == SHADE");
-            }
-
-            if (keyguardFadingAway && oldStatusBarState != SHADE) {
-                mKeyguardViewVisibilityAnimating = true;
-                AnimationProperties animProps = new AnimationProperties()
-                        .setDelay(0)
-                        .setCustomInterpolator(View.ALPHA, Interpolators.FAST_OUT_LINEAR_IN)
-                        .setAnimationEndAction(mSetInvisibleEndAction);
-                if (mAnimateYPos) {
-                    float target = mView.getY() - mView.getHeight() * 0.05f;
-                    int delay = 0;
-                    int duration = 125;
-                    // We animate the Y property separately using the PropertyAnimator, as the panel
-                    // view also needs to update the end position.
-                    mAnimationProperties.setDuration(duration).setDelay(delay);
-                    PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
-                    PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target,
-                            mAnimationProperties,
-                            true /* animate */);
-                    animProps.setDuration(duration)
-                            .setDelay(delay);
-                    log("keyguardFadingAway transition w/ Y Aniamtion");
-                } else {
-                    log("keyguardFadingAway transition w/o Y Animation");
-                }
-                PropertyAnimator.setProperty(
-                        mView, AnimatableProperty.ALPHA, 0f,
-                        animProps,
-                        true /* animate */);
-            } else if (mScreenOffAnimationController.shouldAnimateInKeyguard()) {
-                if (MigrateClocksToBlueprint.isEnabled()) {
-                    log("Using GoneToAodTransition");
-                    mKeyguardViewVisibilityAnimating = false;
-                } else {
-                    log("ScreenOff transition");
-                    mKeyguardViewVisibilityAnimating = true;
-
-                    // Ask the screen off animation controller to animate the keyguard visibility
-                    // for us since it may need to be cancelled due to keyguard lifecycle events.
-                    mScreenOffAnimationController.animateInKeyguard(mView, mSetVisibleEndRunnable);
-                }
-            } else {
-                log("Direct set Visibility to VISIBLE");
-                mView.setVisibility(View.VISIBLE);
-            }
-        } else {
-            if (MigrateClocksToBlueprint.isEnabled()) {
-                log("Using LockscreenToGoneTransition 2");
-            } else {
-                log("Direct set Visibility to GONE");
-                mView.setVisibility(View.GONE);
-                mView.setAlpha(1f);
-            }
-        }
-
-        mLastOccludedState = isOccluded;
-    }
-
-    private final Consumer<Property> mSetInvisibleEndAction = new Consumer<>() {
-        @Override
-        public void accept(Property property) {
-            mKeyguardViewVisibilityAnimating = false;
-            mView.setVisibility(View.INVISIBLE);
-            log("Callback Set Visibility to INVISIBLE");
-        }
-    };
-
-    private final Consumer<Property> mSetGoneEndAction = new Consumer<>() {
-        @Override
-        public void accept(Property property) {
-            mKeyguardViewVisibilityAnimating = false;
-            mView.setVisibility(View.GONE);
-            log("CallbackSet Visibility to GONE");
-        }
-    };
-
-    private final Runnable mSetVisibleEndRunnable = () -> {
-        mKeyguardViewVisibilityAnimating = false;
-        mView.setVisibility(View.VISIBLE);
-        log("Callback Set Visibility to VISIBLE");
-    };
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
index 0305b5e..e76f38c 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
@@ -26,7 +26,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.clocks.ClockMessageBuffers;
 import com.android.systemui.res.R;
@@ -70,7 +69,7 @@
                         context,
                         layoutInflater,
                         resources,
-                        MigrateClocksToBlueprint.isEnabled(),
+
                         com.android.systemui.Flags.clockReactiveVariants()
                 ),
                 context.getString(R.string.lockscreen_clock_id_fallback),
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java
index 4331f52..a887011 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardQsUserSwitchComponent.java
@@ -29,7 +29,7 @@
 @Subcomponent(modules = {KeyguardUserSwitcherModule.class})
 @KeyguardUserSwitcherScope
 public interface KeyguardQsUserSwitchComponent {
-    /** Simple factory for {@link KeyguardUserSwitcherComponent}. */
+    /** Simple factory for {@link KeyguardQsUserSwitchComponent}. */
     @Subcomponent.Factory
     interface Factory {
         KeyguardQsUserSwitchComponent build(@BindsInstance FrameLayout userAvatarContainer);
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java
index 91dd1d6..9a47170 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewComponent.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard.dagger;
 
-import com.android.keyguard.KeyguardStatusViewController;
 import com.android.systemui.shade.ShadeViewStateProvider;
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
 import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
@@ -25,9 +24,7 @@
 import dagger.Subcomponent;
 
 /**
- * Subcomponent for helping work with KeyguardStatusView and its children.
- *
- * TODO: unify this with {@link KeyguardStatusViewComponent}
+ * Subcomponent for helping work with KeyguardStatusBarView and its children.
  */
 @Subcomponent(modules = {KeyguardStatusBarViewModule.class})
 @KeyguardStatusBarViewScope
@@ -41,6 +38,5 @@
                         shadeViewStateProvider);
     }
 
-    /** Builds a {@link KeyguardStatusViewController}. */
     KeyguardStatusBarViewController getKeyguardStatusBarViewController();
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
deleted file mode 100644
index f3014f1..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewComponent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import android.view.Display;
-
-import com.android.keyguard.KeyguardClockSwitchController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Subcomponent for helping work with KeyguardStatusView and its children.
- *
- * TODO: unify this with {@link KeyguardStatusBarViewComponent}
- */
-@Subcomponent(modules = {KeyguardStatusViewModule.class, KeyguardDisplayModule.class})
-@KeyguardStatusViewScope
-public interface KeyguardStatusViewComponent {
-    /** Simple factory for {@link KeyguardStatusViewComponent}. */
-    @Subcomponent.Factory
-    interface Factory {
-        /** Creates {@link KeyguardStatusViewComponent} for a given display. */
-        KeyguardStatusViewComponent build(
-                @BindsInstance KeyguardStatusView presentation,
-                @BindsInstance Display display
-        );
-    }
-
-    /** Builds a {@link com.android.keyguard.KeyguardClockSwitchController}. */
-    KeyguardClockSwitchController getKeyguardClockSwitchController();
-
-    /** Builds a {@link com.android.keyguard.KeyguardStatusViewController}. */
-    KeyguardStatusViewController getKeyguardStatusViewController();
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewModule.java
deleted file mode 100644
index 7575f0e..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewModule.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardSliceView;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.systemui.res.R;
-
-import dagger.Module;
-import dagger.Provides;
-
-/** Dagger module for {@link KeyguardStatusViewComponent}. */
-@Module
-public abstract class KeyguardStatusViewModule {
-    @Provides
-    static KeyguardClockSwitch getKeyguardClockSwitch(KeyguardStatusView keyguardPresentation) {
-        return keyguardPresentation.findViewById(R.id.keyguard_clock_container);
-    }
-
-    @Provides
-    static KeyguardSliceView getKeyguardSliceView(KeyguardClockSwitch keyguardClockSwitch) {
-        return keyguardClockSwitch.findViewById(R.id.keyguard_slice_view);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java
deleted file mode 100644
index 6c2c9f2..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusViewScope.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Scope;
-
-/**
- * Scope annotation for singleton items within the {@link KeyguardStatusViewComponent}.
- */
-@Documented
-@Retention(RUNTIME)
-@Scope
-public @interface KeyguardStatusViewScope {}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherComponent.java
deleted file mode 100644
index 730c14d..0000000
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherComponent.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard.dagger;
-
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Subcomponent for helping work with KeyguardUserSwitcher and its children.
- */
-@Subcomponent(modules = {KeyguardUserSwitcherModule.class})
-@KeyguardUserSwitcherScope
-public interface KeyguardUserSwitcherComponent {
-    /** Simple factory for {@link KeyguardUserSwitcherComponent}. */
-    @Subcomponent.Factory
-    interface Factory {
-        KeyguardUserSwitcherComponent build(
-                @BindsInstance KeyguardUserSwitcherView keyguardUserSwitcherView);
-    }
-
-    /** Builds a {@link com.android.systemui.statusbar.policy.KeyguardUserSwitcherController}. */
-    KeyguardUserSwitcherController getKeyguardUserSwitcherController();
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherModule.java
index b9184f4..1ad2d4c 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherModule.java
@@ -18,7 +18,7 @@
 
 import dagger.Module;
 
-/** Dagger module for {@link KeyguardUserSwitcherComponent}. */
+/** Dagger module for {@link KeyguardQsUserSwitchComponent}. */
 @Module
 public abstract class KeyguardUserSwitcherModule {
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherScope.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherScope.java
index 864472e..12d1949 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherScope.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardUserSwitcherScope.java
@@ -24,7 +24,7 @@
 import javax.inject.Scope;
 
 /**
- * Scope annotation for singleton items within the KeyguardUserSwitcherComponent.
+ * Scope annotation for singleton items within the KeyguardQsUserSwitchComponent.
  */
 @Documented
 @Retention(RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
new file mode 100644
index 0000000..7c141c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeLayout.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_LEFT;
+import static com.android.settingslib.bluetooth.HearingAidInfo.DeviceSide.SIDE_RIGHT;
+
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settingslib.bluetooth.AmbientVolumeUi;
+import com.android.systemui.res.R;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.primitives.Ints;
+
+import java.util.Map;
+
+/**
+ * A view of ambient volume controls.
+ *
+ * <p> It consists of a header with an expand icon and volume sliders for unified control and
+ * separated control for devices in the same set. Toggle the expand icon will make the UI switch
+ * between unified and separated control.
+ */
+public class AmbientVolumeLayout extends LinearLayout implements AmbientVolumeUi {
+
+    @Nullable
+    private AmbientVolumeUiListener mListener;
+    private ImageView mExpandIcon;
+    private ImageView mVolumeIcon;
+    private boolean mExpandable = true;
+    private boolean mExpanded = false;
+    private boolean mMutable = false;
+    private boolean mMuted = false;
+    private final BiMap<Integer, AmbientVolumeSlider> mSideToSliderMap = HashBiMap.create();
+    private int mVolumeLevel = AMBIENT_VOLUME_LEVEL_DEFAULT;
+
+    private final AmbientVolumeSlider.OnChangeListener mSliderOnChangeListener =
+            (slider, value) -> {
+                if (mListener != null) {
+                    final int side = mSideToSliderMap.inverse().get(slider);
+                    mListener.onSliderValueChange(side, value);
+                }
+            };
+
+    public AmbientVolumeLayout(@Nullable Context context) {
+        this(context, /* attrs= */ null);
+    }
+
+    public AmbientVolumeLayout(@Nullable Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, /* defStyleAttr= */ 0);
+    }
+
+    public AmbientVolumeLayout(@Nullable Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, /* defStyleRes= */ 0);
+    }
+
+    public AmbientVolumeLayout(@Nullable Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        inflate(context, R.layout.hearing_device_ambient_volume_layout, /* root= */ this);
+        init();
+    }
+
+    private void init() {
+        mVolumeIcon = requireViewById(R.id.ambient_volume_icon);
+        mVolumeIcon.setImageResource(com.android.settingslib.R.drawable.ic_ambient_volume);
+        mVolumeIcon.setOnClickListener(v -> {
+            if (!mMutable) {
+                return;
+            }
+            setMuted(!mMuted);
+            if (mListener != null) {
+                mListener.onAmbientVolumeIconClick();
+            }
+        });
+        updateVolumeIcon();
+
+        mExpandIcon = requireViewById(R.id.ambient_expand_icon);
+        mExpandIcon.setOnClickListener(v -> {
+            setExpanded(!mExpanded);
+            if (mListener != null) {
+                mListener.onExpandIconClick();
+            }
+        });
+        updateExpandIcon();
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        setVisibility(visible ? VISIBLE : GONE);
+    }
+
+    @Override
+    public void setExpandable(boolean expandable) {
+        mExpandable = expandable;
+        if (!mExpandable) {
+            setExpanded(false);
+        }
+        updateExpandIcon();
+    }
+
+    @Override
+    public boolean isExpandable() {
+        return mExpandable;
+    }
+
+    @Override
+    public void setExpanded(boolean expanded) {
+        if (!mExpandable && expanded) {
+            return;
+        }
+        mExpanded = expanded;
+        updateExpandIcon();
+        updateLayout();
+    }
+
+    @Override
+    public boolean isExpanded() {
+        return mExpanded;
+    }
+
+    @Override
+    public void setMutable(boolean mutable) {
+        mMutable = mutable;
+        if (!mMutable) {
+            mVolumeLevel = AMBIENT_VOLUME_LEVEL_DEFAULT;
+            setMuted(false);
+        }
+        updateVolumeIcon();
+    }
+
+    @Override
+    public boolean isMutable() {
+        return mMutable;
+    }
+
+    @Override
+    public void setMuted(boolean muted) {
+        if (!mMutable && muted) {
+            return;
+        }
+        mMuted = muted;
+        if (mMutable && mMuted) {
+            for (AmbientVolumeSlider slider : mSideToSliderMap.values()) {
+                slider.setValue(slider.getMin());
+            }
+        }
+        updateVolumeIcon();
+    }
+
+    @Override
+    public boolean isMuted() {
+        return mMuted;
+    }
+
+    @Override
+    public void setListener(@Nullable AmbientVolumeUiListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public void setupSliders(@NonNull Map<Integer, BluetoothDevice> sideToDeviceMap) {
+        sideToDeviceMap.forEach((side, device) -> createSlider(side));
+        createSlider(SIDE_UNIFIED);
+
+        LinearLayout controlContainer = requireViewById(R.id.ambient_control_container);
+        controlContainer.removeAllViews();
+        if (!mSideToSliderMap.isEmpty()) {
+            for (int side : VALID_SIDES) {
+                final AmbientVolumeSlider slider = mSideToSliderMap.get(side);
+                if (slider != null) {
+                    controlContainer.addView(slider);
+                }
+            }
+        }
+        updateLayout();
+    }
+
+    @Override
+    public void setSliderEnabled(int side, boolean enabled) {
+        AmbientVolumeSlider slider = mSideToSliderMap.get(side);
+        if (slider != null && slider.isEnabled() != enabled) {
+            slider.setEnabled(enabled);
+            updateLayout();
+        }
+    }
+
+    @Override
+    public void setSliderValue(int side, int value) {
+        AmbientVolumeSlider slider = mSideToSliderMap.get(side);
+        if (slider != null && slider.getValue() != value) {
+            slider.setValue(value);
+            updateVolumeLevel();
+        }
+    }
+
+    @Override
+    public void setSliderRange(int side, int min, int max) {
+        AmbientVolumeSlider slider = mSideToSliderMap.get(side);
+        if (slider != null) {
+            slider.setMin(min);
+            slider.setMax(max);
+        }
+    }
+
+    @Override
+    public void updateLayout() {
+        mSideToSliderMap.forEach((side, slider) -> {
+            if (side == SIDE_UNIFIED) {
+                slider.setVisibility(mExpanded ? GONE : VISIBLE);
+            } else {
+                slider.setVisibility(mExpanded ? VISIBLE : GONE);
+            }
+            if (!slider.isEnabled()) {
+                slider.setValue(slider.getMin());
+            }
+        });
+        updateVolumeLevel();
+    }
+
+    private void updateVolumeLevel() {
+        int leftLevel, rightLevel;
+        if (mExpanded) {
+            leftLevel = getVolumeLevel(SIDE_LEFT);
+            rightLevel = getVolumeLevel(SIDE_RIGHT);
+        } else {
+            final int unifiedLevel = getVolumeLevel(SIDE_UNIFIED);
+            leftLevel = unifiedLevel;
+            rightLevel = unifiedLevel;
+        }
+        mVolumeLevel = Ints.constrainToRange(leftLevel * 5 + rightLevel,
+                AMBIENT_VOLUME_LEVEL_MIN, AMBIENT_VOLUME_LEVEL_MAX);
+        updateVolumeIcon();
+    }
+
+    private int getVolumeLevel(int side) {
+        AmbientVolumeSlider slider = mSideToSliderMap.get(side);
+        if (slider == null || !slider.isEnabled()) {
+            return 0;
+        }
+        return slider.getVolumeLevel();
+    }
+
+    private void updateExpandIcon() {
+        mExpandIcon.setVisibility(mExpandable ? VISIBLE : GONE);
+        mExpandIcon.setRotation(mExpanded ? ROTATION_EXPANDED : ROTATION_COLLAPSED);
+        if (mExpandable) {
+            final int stringRes = mExpanded ? R.string.hearing_devices_ambient_collapse_controls
+                    : R.string.hearing_devices_ambient_expand_controls;
+            mExpandIcon.setContentDescription(mContext.getString(stringRes));
+        } else {
+            mExpandIcon.setContentDescription(null);
+        }
+    }
+
+    private void updateVolumeIcon() {
+        mVolumeIcon.setImageLevel(mMuted ? 0 : mVolumeLevel);
+        if (mMutable) {
+            final int stringRes = mMuted ? R.string.hearing_devices_ambient_unmute
+                    : R.string.hearing_devices_ambient_mute;
+            mVolumeIcon.setContentDescription(mContext.getString(stringRes));
+            mVolumeIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }  else {
+            mVolumeIcon.setContentDescription(null);
+            mVolumeIcon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+        }
+    }
+
+    private void createSlider(int side) {
+        if (mSideToSliderMap.containsKey(side)) {
+            return;
+        }
+        AmbientVolumeSlider slider = new AmbientVolumeSlider(mContext);
+        slider.addOnChangeListener(mSliderOnChangeListener);
+        if (side == SIDE_LEFT) {
+            slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_left));
+        } else if (side == SIDE_RIGHT) {
+            slider.setTitle(mContext.getString(R.string.hearing_devices_ambient_control_right));
+        }
+        mSideToSliderMap.put(side, slider);
+    }
+
+    @VisibleForTesting
+    ImageView getVolumeIcon() {
+        return mVolumeIcon;
+    }
+
+    @VisibleForTesting
+    ImageView getExpandIcon() {
+        return mExpandIcon;
+    }
+
+    @VisibleForTesting
+    Map<Integer, AmbientVolumeSlider> getSliders() {
+        return mSideToSliderMap;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
new file mode 100644
index 0000000..1a068c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/AmbientVolumeSlider.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.accessibility.hearingaid;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.res.R;
+
+import com.google.android.material.slider.Slider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A view of ambient volume slider.
+ * <p> It consists by a title {@link TextView} with a volume control {@link Slider}.
+ */
+public class AmbientVolumeSlider extends LinearLayout {
+
+    private final TextView mTitle;
+    private final Slider mSlider;
+    private final List<OnChangeListener> mChangeListeners = new ArrayList<>();
+    private final Slider.OnSliderTouchListener mSliderTouchListener =
+            new Slider.OnSliderTouchListener() {
+                @Override
+                public void onStartTrackingTouch(@NonNull Slider slider) {
+                    mTrackingTouch = true;
+                }
+
+                @Override
+                public void onStopTrackingTouch(@NonNull Slider slider) {
+                    mTrackingTouch = false;
+                    final int value = Math.round(slider.getValue());
+                    for (OnChangeListener listener : mChangeListeners) {
+                        listener.onValueChange(AmbientVolumeSlider.this, value);
+                    }
+                }
+            };
+    private final Slider.OnChangeListener mSliderChangeListener = new Slider.OnChangeListener() {
+        @Override
+        public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
+            if (fromUser && !mTrackingTouch) {
+                final int roundedValue = Math.round(value);
+                for (OnChangeListener listener : mChangeListeners) {
+                    listener.onValueChange(AmbientVolumeSlider.this, roundedValue);
+                }
+            }
+        }
+    };
+    private boolean mTrackingTouch = false;
+
+    public AmbientVolumeSlider(@Nullable Context context) {
+        this(context, /* attrs= */ null);
+    }
+
+    public AmbientVolumeSlider(@Nullable Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, /* defStyleAttr= */ 0);
+    }
+
+    public AmbientVolumeSlider(@Nullable Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr) {
+        this(context, attrs, defStyleAttr, /* defStyleRes= */ 0);
+    }
+
+    public AmbientVolumeSlider(@Nullable Context context, @Nullable AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        inflate(context, R.layout.hearing_device_ambient_volume_slider, /* root= */ this);
+        mTitle = requireViewById(R.id.ambient_volume_slider_title);
+        mSlider = requireViewById(R.id.ambient_volume_slider);
+        mSlider.addOnSliderTouchListener(mSliderTouchListener);
+        mSlider.addOnChangeListener(mSliderChangeListener);
+    }
+
+    /**
+     * Sets title for the ambient volume slider.
+     * <p> If text is null or empty, then {@link TextView} is hidden.
+     */
+    public void setTitle(@Nullable String text) {
+        mTitle.setText(text);
+        mTitle.setVisibility(TextUtils.isEmpty(text) ? GONE : VISIBLE);
+    }
+
+    /** Gets title for the ambient volume slider. */
+    public CharSequence getTitle() {
+        return mTitle.getText();
+    }
+
+    /**
+     * Adds the callback to the ambient volume slider to get notified when the value is changed by
+     * user.
+     * <p> Note: The {@link OnChangeListener#onValueChange(AmbientVolumeSlider, int)} will be
+     * called when user's finger take off from the slider.
+     */
+    public void addOnChangeListener(@Nullable OnChangeListener listener) {
+        if (listener == null) {
+            return;
+        }
+        mChangeListeners.add(listener);
+    }
+
+    /** Sets max value to the ambient volume slider. */
+    public void setMax(float max) {
+        mSlider.setValueTo(max);
+    }
+
+    /** Gets max value from the ambient volume slider. */
+    public float getMax() {
+        return mSlider.getValueTo();
+    }
+
+    /** Sets min value to the ambient volume slider. */
+    public void setMin(float min) {
+        mSlider.setValueFrom(min);
+    }
+
+    /** Gets min value from the ambient volume slider. */
+    public float getMin() {
+        return mSlider.getValueFrom();
+    }
+
+    /** Sets value to the ambient volume slider. */
+    public void setValue(float value) {
+        mSlider.setValue(value);
+    }
+
+    /** Gets value from the ambient volume slider. */
+    public float getValue() {
+        return mSlider.getValue();
+    }
+
+    /** Sets the enable state to the ambient volume slider. */
+    public void setEnabled(boolean enabled) {
+        mSlider.setEnabled(enabled);
+    }
+
+    /** Gets the enable state of the ambient volume slider. */
+    public boolean isEnabled() {
+        return mSlider.isEnabled();
+    }
+
+    /**
+     * Gets the volume value of the ambient volume slider.
+     * <p> The volume level is divided into 5 levels:
+     * Level 0 corresponds to the minimum volume value. The range between the minimum and maximum
+     * volume is divided into 4 equal intervals, represented by levels 1 to 4.
+     */
+    public int getVolumeLevel() {
+        if (!mSlider.isEnabled()) {
+            return 0;
+        }
+        final double min = mSlider.getValueFrom();
+        final double max = mSlider.getValueTo();
+        final double levelGap = (max - min) / 4.0;
+        final double value = mSlider.getValue();
+        return (int) Math.ceil((value - min) / levelGap);
+    }
+
+    /** Interface definition for a callback invoked when a slider's value is changed. */
+    public interface OnChangeListener {
+        /** Called when the finger is take off from the slider. */
+        void onValueChange(@NonNull AmbientVolumeSlider slider, int value);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index 56435df..73aabc3 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -52,10 +52,12 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.settingslib.bluetooth.AmbientVolumeUiController;
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.accessibility.hearingaid.HearingDevicesListAdapter.HearingDeviceItemCallback;
 import com.android.systemui.animation.DialogTransitionAnimator;
 import com.android.systemui.bluetooth.qsdialog.ActiveHearingDeviceItemFactory;
@@ -108,7 +110,6 @@
 
     private SystemUIDialog mDialog;
 
-    private RecyclerView mDeviceList;
     private List<DeviceItem> mHearingDeviceItemList;
     private HearingDevicesListAdapter mDeviceListAdapter;
 
@@ -134,6 +135,8 @@
                 }
             };
 
+    private AmbientVolumeUiController mAmbientController;
+
     private final List<DeviceItemFactory> mHearingDeviceItemFactoryList = List.of(
             new ActiveHearingDeviceItemFactory(),
             new AvailableHearingDeviceItemFactory(),
@@ -225,13 +228,17 @@
     public void onActiveDeviceChanged(@Nullable CachedBluetoothDevice activeDevice,
             int bluetoothProfile) {
         refreshDeviceUi();
-        if (mPresetController != null) {
-            mPresetController.setDevice(getActiveHearingDevice());
-            mMainHandler.post(() -> {
+        mMainHandler.post(() -> {
+            CachedBluetoothDevice device = getActiveHearingDevice();
+            if (mPresetController != null) {
+                mPresetController.setDevice(device);
                 mPresetLayout.setVisibility(
                         mPresetController.isPresetControlAvailable() ? VISIBLE : GONE);
-            });
-        }
+            }
+            if (mAmbientController != null) {
+                mAmbientController.loadDevice(device);
+            }
+        });
     }
 
     @Override
@@ -272,13 +279,13 @@
         }
 
         mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW, mLaunchSourceId);
-        mDeviceList = dialog.requireViewById(R.id.device_list);
-        mPresetLayout = dialog.requireViewById(R.id.preset_layout);
-        mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
 
         setupDeviceListView(dialog);
-        setupPresetSpinner(dialog);
         setupPairNewDeviceButton(dialog);
+        setupPresetSpinner(dialog);
+        if (com.android.settingslib.flags.Flags.hearingDevicesAmbientVolumeControl()) {
+            setupAmbientControls();
+        }
         if (com.android.systemui.Flags.hearingDevicesDialogRelatedTools()) {
             setupRelatedToolsView(dialog);
         }
@@ -286,41 +293,50 @@
 
     @Override
     public void onStart(@NonNull SystemUIDialog dialog) {
-        if (mLocalBluetoothManager == null) {
-            return;
-        }
-        mLocalBluetoothManager.getEventManager().registerCallback(this);
-        if (mPresetController != null) {
-            mPresetController.registerHapCallback();
-        }
+        ThreadUtils.postOnBackgroundThread(() -> {
+            if (mLocalBluetoothManager != null) {
+                mLocalBluetoothManager.getEventManager().registerCallback(this);
+            }
+            if (mPresetController != null) {
+                mPresetController.registerHapCallback();
+            }
+            if (mAmbientController != null) {
+                mAmbientController.start();
+            }
+        });
     }
 
     @Override
     public void onStop(@NonNull SystemUIDialog dialog) {
-        if (mLocalBluetoothManager == null) {
-            return;
-        }
-
-        if (mPresetController != null) {
-            mPresetController.unregisterHapCallback();
-        }
-        mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+        ThreadUtils.postOnBackgroundThread(() -> {
+            if (mLocalBluetoothManager != null) {
+                mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+            }
+            if (mPresetController != null) {
+                mPresetController.unregisterHapCallback();
+            }
+            if (mAmbientController != null) {
+                mAmbientController.stop();
+            }
+        });
     }
 
     private void setupDeviceListView(SystemUIDialog dialog) {
-        mDeviceList.setLayoutManager(new LinearLayoutManager(dialog.getContext()));
+        final RecyclerView deviceList = dialog.requireViewById(R.id.device_list);
+        deviceList.setLayoutManager(new LinearLayoutManager(dialog.getContext()));
         mHearingDeviceItemList = getHearingDeviceItemList();
         mDeviceListAdapter = new HearingDevicesListAdapter(mHearingDeviceItemList, this);
-        mDeviceList.setAdapter(mDeviceListAdapter);
+        deviceList.setAdapter(mDeviceListAdapter);
     }
 
     private void setupPresetSpinner(SystemUIDialog dialog) {
         mPresetController = new HearingDevicesPresetsController(mProfileManager, mPresetCallback);
         mPresetController.setDevice(getActiveHearingDevice());
 
+        mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
         mPresetInfoAdapter = new HearingDevicesSpinnerAdapter(dialog.getContext());
         mPresetSpinner.setAdapter(mPresetInfoAdapter);
-        // disable redundant Touch & Hold accessibility action for Switch Access
+        // Disable redundant Touch & Hold accessibility action for Switch Access
         mPresetSpinner.setAccessibilityDelegate(new View.AccessibilityDelegate() {
             @Override
             public void onInitializeAccessibilityNodeInfo(@NonNull View host,
@@ -349,12 +365,20 @@
             }
         });
 
+        mPresetLayout = dialog.requireViewById(R.id.preset_layout);
         mPresetLayout.setVisibility(mPresetController.isPresetControlAvailable() ? VISIBLE : GONE);
     }
 
+    private void setupAmbientControls() {
+        final AmbientVolumeLayout ambientLayout = mDialog.requireViewById(R.id.ambient_layout);
+        mAmbientController = new AmbientVolumeUiController(
+                mDialog.getContext(), mLocalBluetoothManager, ambientLayout);
+        mAmbientController.setShowUiWhenLocalDataExist(false);
+        mAmbientController.loadDevice(getActiveHearingDevice());
+    }
+
     private void setupPairNewDeviceButton(SystemUIDialog dialog) {
         final Button pairButton = dialog.requireViewById(R.id.pair_new_device_button);
-
         pairButton.setVisibility(mShowPairNewDevice ? VISIBLE : GONE);
         if (mShowPairNewDevice) {
             pairButton.setOnClickListener(v -> {
diff --git a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
index 232b629..11a6cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt
@@ -21,8 +21,11 @@
 import android.window.OnBackInvokedCallback
 import android.window.OnBackInvokedDispatcher
 import android.window.WindowOnBackInvokedDispatcher
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.CoreStartable
+import com.android.systemui.Flags.glanceableHubBackAction
 import com.android.systemui.Flags.predictiveBackAnimateShade
+import com.android.systemui.communal.domain.interactor.CommunalBackActionInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -35,7 +38,6 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** Handles requests to go back either from a button or gesture. */
 @SysUISingleton
@@ -50,6 +52,7 @@
     private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor,
     private val shadeBackActionInteractor: ShadeBackActionInteractor,
     private val qsController: QuickSettingsController,
+    private val communalBackActionInteractor: CommunalBackActionInteractor,
 ) : CoreStartable {
 
     private var isCallbackRegistered = false
@@ -111,8 +114,11 @@
             shadeBackActionInteractor.animateCollapseQs(false)
             return true
         }
-        if (shadeBackActionInteractor.closeUserSwitcherIfOpen()) {
-            return true
+        if (glanceableHubBackAction()) {
+            if (communalBackActionInteractor.canBeDismissed()) {
+                communalBackActionInteractor.onBackPressed()
+                return true
+            }
         }
         if (shouldBackBeHandled()) {
             if (shadeBackActionInteractor.canBeCollapsed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 4c2dc41..d8c628f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -155,6 +155,7 @@
                     override fun onAnimationEnd(animation: Animator) {
                         drawDwell = false
                         resetDwellAlpha()
+                        invalidate()
                     }
                 })
                 start()
@@ -191,6 +192,7 @@
                     override fun onAnimationEnd(animation: Animator) {
                         drawDwell = false
                         resetDwellAlpha()
+                        invalidate()
                     }
                 })
                 start()
@@ -248,6 +250,7 @@
 
                 override fun onAnimationEnd(animation: Animator) {
                     drawDwell = false
+                    invalidate()
                 }
             })
             start()
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
index ca479f5..bee1f74 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
@@ -25,23 +25,25 @@
 import com.android.systemui.biometrics.BiometricDisplayListener.SensorType.Generic
 
 /**
- * A listener for keeping overlays for biometric sensors aligned with the physical device
- * device's screen. The [onChanged] will be dispatched on the [handler]
- * whenever a relevant change to the device's configuration (orientation, fold, display change,
- * etc.) may require the UI to change for the given [sensorType].
+ * A listener for keeping overlays for biometric sensors aligned with the physical device device's
+ * screen. The [onChanged] will be dispatched on the [handler] whenever a relevant change to the
+ * device's configuration (orientation, fold, display change, etc.) may require the UI to change for
+ * the given [sensorType].
  */
 class BiometricDisplayListener(
     private val context: Context,
     private val displayManager: DisplayManager,
     private val handler: Handler,
     private val sensorType: SensorType = SensorType.Generic,
-    private val onChanged: () -> Unit
+    private val onChanged: () -> Unit,
 ) : DisplayManager.DisplayListener {
 
     private var cachedDisplayInfo = DisplayInfo()
 
     override fun onDisplayAdded(displayId: Int) {}
+
     override fun onDisplayRemoved(displayId: Int) {}
+
     override fun onDisplayChanged(displayId: Int) {
         traceSection({ "BiometricDisplayListener($sensorType)#onDisplayChanged" }) {
             val rotationChanged = didRotationChange()
@@ -69,7 +71,7 @@
         displayManager.registerDisplayListener(
             this,
             handler,
-            DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+            DisplayManager.EVENT_TYPE_DISPLAY_CHANGED,
         )
     }
 
@@ -81,14 +83,15 @@
     /**
      * Type of sensor to determine what kind of display changes require layouts.
      *
-     * The [Generic] type should be used in cases where the modality can vary, such as
-     * biometric prompt (and this object will likely change as multi-mode auth is added).
+     * The [Generic] type should be used in cases where the modality can vary, such as biometric
+     * prompt (and this object will likely change as multi-mode auth is added).
      */
     sealed class SensorType {
         data object Generic : SensorType()
+
         data object UnderDisplayFingerprint : SensorType()
-        data class SideFingerprint(
-            val properties: FingerprintSensorPropertiesInternal
-        ) : SensorType()
+
+        data class SideFingerprint(val properties: FingerprintSensorPropertiesInternal) :
+            SensorType()
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
index 9cfb5be..b294dd1 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt
@@ -41,6 +41,7 @@
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.util.time.SystemClock
 import dagger.assisted.Assisted
@@ -68,6 +69,7 @@
     private val uiEventLogger: UiEventLogger,
     private val logger: BluetoothTileDialogLogger,
     private val systemuiDialogFactory: SystemUIDialog.Factory,
+    private val shadeDialogContextInteractor: ShadeDialogContextInteractor,
 ) : SystemUIDialog.Delegate {
 
     private val mutableBluetoothStateToggle: MutableStateFlow<Boolean?> = MutableStateFlow(null)
@@ -105,7 +107,7 @@
     }
 
     override fun createDialog(): SystemUIDialog {
-        return systemuiDialogFactory.create(this)
+        return systemuiDialogFactory.create(this, shadeDialogContextInteractor.context)
     }
 
     override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {
@@ -405,10 +407,11 @@
                     }
 
                     // updating icon colors
-                    val tintColor = context.getColor(
-                        if (item.isActive) InternalR.color.materialColorOnPrimaryContainer
-                        else InternalR.color.materialColorOnSurface
-                    )
+                    val tintColor =
+                        context.getColor(
+                            if (item.isActive) InternalR.color.materialColorOnPrimaryContainer
+                            else InternalR.color.materialColorOnSurface
+                        )
 
                     // update icons
                     iconView.apply {
diff --git a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
index 6c78b8b..e6d6293 100644
--- a/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt
@@ -133,7 +133,7 @@
                     listener,
                     null,
                     /* eventFlags */ 0,
-                    DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
+                    DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS,
                 )
 
                 awaitClose { displayManager.unregisterDisplayListener(listener) }
@@ -181,10 +181,11 @@
             .logDiffForTable(tableBuffer, TABLE_PREFIX_LINEAR, TABLE_COLUMN_BRIGHTNESS, null)
             .stateIn(applicationScope, SharingStarted.WhileSubscribed(), LinearBrightness(0f))
 
-    override val isBrightnessOverriddenByWindow = brightnessInfo
-        .filterNotNull()
-        .map { it.isBrightnessOverrideByWindow }
-        .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
+    override val isBrightnessOverriddenByWindow =
+        brightnessInfo
+            .filterNotNull()
+            .map { it.isBrightnessOverrideByWindow }
+            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
 
     override fun setTemporaryBrightness(value: LinearBrightness) {
         apiQueue.trySend(SetBrightnessMethod.Temporary(value))
diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt
index aef5f1f..e6f0245 100644
--- a/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt
@@ -21,14 +21,17 @@
 
 /**
  * Models an icon, that can either be already [loaded][Icon.Loaded] or be a [reference]
- * [Icon.Resource] to a resource.
+ * [Icon.Resource] to a resource. In case of [Loaded], the resource ID [res] is optional.
  */
 sealed class Icon {
     abstract val contentDescription: ContentDescription?
 
-    data class Loaded(
+    data class Loaded
+    @JvmOverloads
+    constructor(
         val drawable: Drawable,
         override val contentDescription: ContentDescription?,
+        @DrawableRes val res: Int? = null,
     ) : Icon()
 
     data class Resource(
@@ -37,6 +40,11 @@
     ) : Icon()
 }
 
-/** Creates [Icon.Loaded] for a given drawable with an optional [contentDescription]. */
-fun Drawable.asIcon(contentDescription: ContentDescription? = null): Icon.Loaded =
-    Icon.Loaded(this, contentDescription)
+/**
+ * Creates [Icon.Loaded] for a given drawable with an optional [contentDescription] and an optional
+ * [res].
+ */
+fun Drawable.asIcon(
+    contentDescription: ContentDescription? = null,
+    @DrawableRes res: Int? = null,
+): Icon.Loaded = Icon.Loaded(this, contentDescription, res)
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/ChoreographerUtils.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/ChoreographerUtils.kt
new file mode 100644
index 0000000..cc7a7bf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/ChoreographerUtils.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.ui.view
+
+import android.view.Choreographer
+import android.view.View
+import com.android.app.tracing.coroutines.TrackTracer
+import kotlin.coroutines.resume
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+/** utilities related to [Choreographer]. */
+interface ChoreographerUtils {
+    /**
+     * Waits until the next [view] doFrame is completed.
+     *
+     * Note that this is expected to work properly when called from any thread. If called during a
+     * doFrame, it waits for the next one to be completed.
+     *
+     * This differs from [kotlinx.coroutines.android.awaitFrame] as it uses
+     * [Handler.postAtFrontOfQueue] instead of [Handler.post] when called from a thread different
+     * than the UI thread for that view. Using [Handler.post] might lead to posting the runnable
+     * after a few frame, effectively missing the "next do frame".
+     */
+    suspend fun waitUntilNextDoFrameDone(view: View)
+}
+
+object ChoreographerUtilsImpl : ChoreographerUtils {
+    private val t = TrackTracer("ChoreographerUtils")
+
+    override suspend fun waitUntilNextDoFrameDone(view: View) {
+        t.traceAsync("waitUntilNextDoFrameDone") { waitUntilNextDoFrameDoneTraced(view) }
+    }
+
+    suspend fun waitUntilNextDoFrameDoneTraced(view: View) {
+        suspendCancellableCoroutine { cont ->
+            val frameCallback =
+                Choreographer.FrameCallback {
+                    t.instant { "We're in doFrame, waiting for it to end." }
+                    view.handler.postAtFrontOfQueue {
+                        t.instant { "DoFrame ended." }
+                        cont.resume(Unit)
+                    }
+                }
+            view.runOnUiThreadUrgently {
+                t.instant { "Waiting for next doFrame" }
+                val choreographer = Choreographer.getInstance()
+                cont.invokeOnCancellation { choreographer.removeFrameCallback(frameCallback) }
+                choreographer.postFrameCallback(frameCallback)
+            }
+        }
+    }
+
+    /**
+     * Execute [r] on the view UI thread, taking priority over everything else scheduled there. Runs
+     * directly if we're already in the correct thread.
+     */
+    private fun View.runOnUiThreadUrgently(r: () -> Unit) {
+        if (handler.looper.isCurrentThread) {
+            r()
+        } else {
+            handler.postAtFrontOfQueue(r)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/FakeChoreographerUtils.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/FakeChoreographerUtils.kt
new file mode 100644
index 0000000..2f097b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/FakeChoreographerUtils.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.common.ui.view
+
+import android.view.View
+import kotlinx.coroutines.CompletableDeferred
+
+class FakeChoreographerUtils : ChoreographerUtils {
+
+    private var pendingDeferred: CompletableDeferred<Unit>? = null
+
+    override suspend fun waitUntilNextDoFrameDone(view: View) {
+        getDeferred().await()
+        clearDeferred()
+    }
+
+    /**
+     * Called from tests when it's time to complete the doFrame. It works also if it's called before
+     * [waitUntilNextDoFrameDone].
+     */
+    fun completeDoFrame() {
+        getDeferred().complete(Unit)
+    }
+
+    @Synchronized
+    private fun getDeferred(): CompletableDeferred<Unit> {
+        if (pendingDeferred == null) {
+            pendingDeferred = CompletableDeferred()
+        }
+        return pendingDeferred!!
+    }
+
+    @Synchronized
+    private fun clearDeferred() {
+        pendingDeferred = null
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
index 26abb48..73c0179 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalSettingsRepository.kt
@@ -55,6 +55,8 @@
     /** A [CommunalEnabledState] for the specified user. */
     fun getEnabledState(user: UserInfo): Flow<CommunalEnabledState>
 
+    fun getScreensaverEnabledState(user: UserInfo): Flow<Boolean>
+
     /**
      * Returns true if any glanceable hub functionality should be enabled via configs and flags.
      *
@@ -138,6 +140,20 @@
             .flowOn(bgDispatcher)
     }
 
+    override fun getScreensaverEnabledState(user: UserInfo): Flow<Boolean> =
+        secureSettings
+            .observerFlow(userId = user.id, names = arrayOf(Settings.Secure.SCREENSAVER_ENABLED))
+            // Force an update
+            .onStart { emit(Unit) }
+            .map {
+                secureSettings.getIntForUser(
+                    Settings.Secure.SCREENSAVER_ENABLED,
+                    SCREENSAVER_ENABLED_SETTING_DEFAULT,
+                    user.id,
+                ) == 1
+            }
+            .flowOn(bgDispatcher)
+
     override fun getAllowedByDevicePolicy(user: UserInfo): Flow<Boolean> =
         broadcastDispatcher
             .broadcastFlow(
@@ -182,6 +198,7 @@
     companion object {
         const val GLANCEABLE_HUB_BACKGROUND_SETTING = "glanceable_hub_background"
         private const val ENABLED_SETTING_DEFAULT = 1
+        private const val SCREENSAVER_ENABLED_SETTING_DEFAULT = 0
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt
new file mode 100644
index 0000000..2ccf96a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.domain.interactor
+
+import com.android.systemui.communal.shared.model.CommunalScenes
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import javax.inject.Inject
+
+/**
+ * {@link CommunalBackActionInteractor} is responsible for handling back gestures on the glanceable
+ * hub. When invoked SystemUI should navigate back to the lockscreen.
+ */
+@SysUISingleton
+class CommunalBackActionInteractor
+@Inject
+constructor(
+    private val communalInteractor: CommunalInteractor,
+    private val communalSceneInteractor: CommunalSceneInteractor,
+    private val sceneInteractor: SceneInteractor,
+) {
+    fun canBeDismissed(): Boolean {
+        return communalInteractor.isCommunalShowing.value
+    }
+
+    fun onBackPressed() {
+        if (SceneContainerFlag.isEnabled) {
+            // TODO(b/384610333): Properly determine whether to go to dream or lockscreen on back.
+            sceneInteractor.changeScene(
+                toScene = Scenes.Lockscreen,
+                loggingReason = "CommunalBackActionInteractor",
+            )
+        } else {
+            communalSceneInteractor.changeScene(
+                newScene = CommunalScenes.Blank,
+                loggingReason = "CommunalBackActionInteractor",
+            )
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index ea42869..947113d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -285,7 +285,7 @@
      * use [isIdleOnCommunal].
      */
     // TODO(b/323215860): rename to something more appropriate after cleaning up usages
-    val isCommunalShowing: Flow<Boolean> =
+    val isCommunalShowing: StateFlow<Boolean> =
         flow { emit(SceneContainerFlag.isEnabled) }
             .flatMapLatest { sceneContainerEnabled ->
                 if (sceneContainerEnabled) {
@@ -304,10 +304,10 @@
                 columnName = "isCommunalShowing",
                 initialValue = false,
             )
-            .shareIn(
+            .stateIn(
                 scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                replay = 1,
+                started = SharingStarted.Eagerly,
+                initialValue = false,
             )
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
index 862b05b..c1f21e40 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSettingsInteractor.kt
@@ -69,6 +69,12 @@
             // Start this eagerly since the value is accessed synchronously in many places.
             .stateIn(scope = bgScope, started = SharingStarted.Eagerly, initialValue = false)
 
+    /** Whether or not screensaver (dreams) is enabled for the currently selected user. */
+    val isScreensaverEnabled: Flow<Boolean> =
+        userInteractor.selectedUserInfo.flatMapLatest { user ->
+            repository.getScreensaverEnabledState(user)
+        }
+
     /**
      * Returns true if any glanceable hub functionality should be enabled via configs and flags.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalUiEvent.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalUiEvent.kt
index 4711d88..3f14252 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalUiEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalUiEvent.kt
@@ -67,7 +67,9 @@
     @UiEvent(doc = "User cancels the swipe gesture to exit the Communal Hub to go to Dream")
     COMMUNAL_HUB_TO_DREAM_SWIPE_CANCEL(1865),
     @UiEvent(doc = "A transition from Dream to Communal Hub starts due to dream awakening")
-    DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START(1866);
+    DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START(1866),
+    @UiEvent(doc = "User tapped the button on Communal Hub to go to Dream")
+    COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP(2065);
 
     override fun getId(): Int {
         return id
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModel.kt
index 6bafd14f..051cb41 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalAppWidgetViewModel.kt
@@ -83,7 +83,7 @@
     }
 
     private suspend fun handleSetListener(appWidgetId: Int, listener: AppWidgetHostListener) =
-        withContextTraced("$TAG#setListenerInner", backgroundContext) {
+        withContextTraced("${TAG}_$appWidgetId#setListenerInner", backgroundContext) {
             if (
                 multiUserHelper.glanceableHubHsumFlagEnabled &&
                     multiUserHelper.isInHeadlessSystemUser()
@@ -92,13 +92,19 @@
                 // remotely in the foreground user, and therefore the host listener needs to be
                 // registered through the widget manager.
                 with(glanceableHubWidgetManagerLazy.get()) {
-                    setAppWidgetHostListener(appWidgetId, listenerDelegateFactory.create(listener))
+                    setAppWidgetHostListener(
+                        appWidgetId,
+                        listenerDelegateFactory.create("${TAG}_$appWidgetId", listener),
+                    )
                 }
             } else {
                 // Instead of setting the view as the listener directly, we wrap the view in a
                 // delegate which ensures the callbacks always get called on the main thread.
                 with(appWidgetHostLazy.get()) {
-                    setListener(appWidgetId, listenerDelegateFactory.create(listener))
+                    setListener(
+                        appWidgetId,
+                        listenerDelegateFactory.create("${TAG}_$appWidgetId", listener),
+                    )
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
index 7d5b196..bbb1686 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModel.kt
@@ -18,10 +18,17 @@
 
 import android.annotation.SuppressLint
 import android.app.DreamManager
+import android.content.Intent
+import android.provider.Settings
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
+import com.android.systemui.communal.shared.log.CommunalUiEvent
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.util.kotlin.isDevicePluggedIn
+import com.android.systemui.util.kotlin.sample
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import kotlin.coroutines.CoroutineContext
@@ -31,7 +38,6 @@
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.receiveAsFlow
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
@@ -41,7 +47,10 @@
 constructor(
     @Background private val backgroundContext: CoroutineContext,
     batteryController: BatteryController,
+    private val settingsInteractor: CommunalSettingsInteractor,
+    private val activityStarter: ActivityStarter,
     private val dreamManager: DreamManager,
+    private val uiEventLogger: UiEventLogger,
 ) : ExclusiveActivatable() {
 
     private val _requests = Channel<Unit>(Channel.BUFFERED)
@@ -49,23 +58,32 @@
     /** Whether we should show a button on hub to switch to dream. */
     @SuppressLint("MissingPermission")
     val shouldShowDreamButtonOnHub =
-        batteryController
-            .isDevicePluggedIn()
-            .distinctUntilChanged()
-            .map { isPluggedIn -> isPluggedIn && dreamManager.canStartDreaming(true) }
-            .flowOn(backgroundContext)
+        batteryController.isDevicePluggedIn().distinctUntilChanged().flowOn(backgroundContext)
 
     /** Handle a tap on the "show dream" button. */
     fun onShowDreamButtonTap() {
+        uiEventLogger.log(CommunalUiEvent.COMMUNAL_HUB_SHOW_DREAM_BUTTON_TAP)
         _requests.trySend(Unit)
     }
 
     @SuppressLint("MissingPermission")
     override suspend fun onActivated(): Nothing = coroutineScope {
         launch {
-            _requests.receiveAsFlow().collectLatest {
-                withContext(backgroundContext) { dreamManager.startDream() }
-            }
+            _requests
+                .receiveAsFlow()
+                .sample(settingsInteractor.isScreensaverEnabled)
+                .collectLatest { enabled ->
+                    withContext(backgroundContext) {
+                        if (enabled) {
+                            dreamManager.startDream()
+                        } else {
+                            activityStarter.postStartActivityDismissingKeyguard(
+                                Intent(Settings.ACTION_DREAM_SETTINGS),
+                                0,
+                            )
+                        }
+                    }
+                }
         }
 
         awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt
index 7d80acd..c0f7caa 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/AppWidgetHostListenerDelegate.kt
@@ -19,11 +19,12 @@
 import android.appwidget.AppWidgetHost.AppWidgetHostListener
 import android.appwidget.AppWidgetProviderInfo
 import android.widget.RemoteViews
-import com.android.systemui.dagger.qualifiers.Main
+import com.android.app.tracing.coroutines.launchTraced
+import com.android.systemui.dagger.qualifiers.Application
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import java.util.concurrent.Executor
+import kotlinx.coroutines.CoroutineScope
 
 /**
  * Wrapper for an [AppWidgetHostListener] to ensure the callbacks are executed on the main thread.
@@ -31,24 +32,27 @@
 class AppWidgetHostListenerDelegate
 @AssistedInject
 constructor(
-    @Main private val mainExecutor: Executor,
+    @Application private val mainScope: CoroutineScope,
+    @Assisted private val tag: String,
     @Assisted private val listener: AppWidgetHostListener,
 ) : AppWidgetHostListener {
 
     @AssistedFactory
     fun interface Factory {
-        fun create(listener: AppWidgetHostListener): AppWidgetHostListenerDelegate
+        fun create(tag: String, listener: AppWidgetHostListener): AppWidgetHostListenerDelegate
     }
 
     override fun onUpdateProviderInfo(appWidget: AppWidgetProviderInfo?) {
-        mainExecutor.execute { listener.onUpdateProviderInfo(appWidget) }
+        mainScope.launchTraced("$tag#onUpdateProviderInfo") {
+            listener.onUpdateProviderInfo(appWidget)
+        }
     }
 
     override fun updateAppWidget(views: RemoteViews?) {
-        mainExecutor.execute { listener.updateAppWidget(views) }
+        mainScope.launchTraced("$tag#updateAppWidget") { listener.updateAppWidget(views) }
     }
 
     override fun onViewDataChanged(viewId: Int) {
-        mainExecutor.execute { listener.onViewDataChanged(viewId) }
+        mainScope.launchTraced("$tag#onViewDataChanged") { listener.onViewDataChanged(viewId) }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt b/packages/SystemUI/src/com/android/systemui/compose/ComposeModule.kt
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt
copy to packages/SystemUI/src/com/android/systemui/compose/ComposeModule.kt
index 4be12bd..31b6f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/ComposeModule.kt
@@ -14,17 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.compose
 
-import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.CoreStartable
 import dagger.Binds
 import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
 
 @Module
-abstract class PromotedNotificationsModule {
+interface ComposeModule {
     @Binds
-    @SysUISingleton
-    abstract fun bindPromotedNotificationsProvider(
-        impl: PromotedNotificationsProviderImpl
-    ): PromotedNotificationsProvider
+    @IntoMap
+    @ClassKey(ComposeTracingStartable::class)
+    fun composeTracing(impl: ComposeTracingStartable): CoreStartable
 }
diff --git a/packages/SystemUI/src/com/android/systemui/compose/ComposeTracingStartable.kt b/packages/SystemUI/src/com/android/systemui/compose/ComposeTracingStartable.kt
new file mode 100644
index 0000000..a015900
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/compose/ComposeTracingStartable.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(InternalComposeTracingApi::class)
+
+package com.android.systemui.compose
+
+import android.os.Trace
+import android.util.Log
+import androidx.compose.runtime.Composer
+import androidx.compose.runtime.CompositionTracer
+import androidx.compose.runtime.InternalComposeTracingApi
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.statusbar.commandline.ParseableCommand
+import java.io.PrintWriter
+import javax.inject.Inject
+
+private const val TAG = "ComposeTracingStartable"
+private const val COMMAND_NAME = "composition-tracing"
+private const val SUBCOMMAND_ENABLE = "enable"
+private const val SUBCOMMAND_DISABLE = "disable"
+
+/**
+ * Sets up a [Command] to enable or disable Composition tracing.
+ *
+ * Usage:
+ * ```
+ * adb shell cmd statusbar composition-tracing [enable|disable]
+ * ${ANDROID_BUILD_TOP}/external/perfetto/tools/record_android_trace -c ${ANDROID_BUILD_TOP}/prebuilts/tools/linux-x86_64/perfetto/configs/trace_config_detailed.textproto
+ * ```
+ */
+@SysUISingleton
+class ComposeTracingStartable @Inject constructor(private val commandRegistry: CommandRegistry) :
+    CoreStartable {
+    @OptIn(InternalComposeTracingApi::class)
+    override fun start() {
+        Log.i(TAG, "Set up Compose tracing command")
+        commandRegistry.registerCommand(COMMAND_NAME) { CompositionTracingCommand() }
+    }
+}
+
+private class CompositionTracingCommand : ParseableCommand(COMMAND_NAME) {
+    val enable by subCommand(EnableCommand())
+    val disable by subCommand(DisableCommand())
+
+    override fun execute(pw: PrintWriter) {
+        if ((enable != null) xor (disable != null)) {
+            enable?.execute(pw)
+            disable?.execute(pw)
+        } else {
+            help(pw)
+        }
+    }
+}
+
+private class EnableCommand : ParseableCommand(SUBCOMMAND_ENABLE) {
+    override fun execute(pw: PrintWriter) {
+        val msg = "Enabled Composition tracing"
+        Log.i(TAG, msg)
+        pw.println(msg)
+        enableCompositionTracing()
+    }
+
+    private fun enableCompositionTracing() {
+        Composer.setTracer(
+            object : CompositionTracer {
+                override fun traceEventStart(key: Int, dirty1: Int, dirty2: Int, info: String) {
+                    Trace.traceBegin(Trace.TRACE_TAG_APP, info)
+                }
+
+                override fun traceEventEnd() = Trace.traceEnd(Trace.TRACE_TAG_APP)
+
+                override fun isTraceInProgress(): Boolean = Trace.isEnabled()
+            }
+        )
+    }
+}
+
+private class DisableCommand : ParseableCommand(SUBCOMMAND_DISABLE) {
+    override fun execute(pw: PrintWriter) {
+        val msg = "Disabled Composition tracing"
+        Log.i(TAG, msg)
+        pw.println(msg)
+        disableCompositionTracing()
+    }
+
+    private fun disableCompositionTracing() {
+        Composer.setTracer(null)
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 9ae106c..014c0db 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -267,6 +267,7 @@
     }
 
     @Provides
+    @Nullable
     @Singleton
     static VirtualDeviceManager provideVirtualDeviceManager(Context context) {
         return context.getSystemService(VirtualDeviceManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index d6f8957..7ebe52f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -54,6 +54,7 @@
 import com.android.systemui.common.usagestats.data.CommonUsageStatsDataLayerModule;
 import com.android.systemui.communal.dagger.CommunalModule;
 import com.android.systemui.complication.dagger.ComplicationComponent;
+import com.android.systemui.compose.ComposeModule;
 import com.android.systemui.controls.dagger.ControlsModule;
 import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -133,6 +134,7 @@
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProvider;
 import com.android.systemui.statusbar.notification.people.PeopleHubModule;
 import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
@@ -141,7 +143,6 @@
 import com.android.systemui.statusbar.phone.ConfigurationControllerModule;
 import com.android.systemui.statusbar.phone.LetterboxModule;
 import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.PolicyModule;
 import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
@@ -214,6 +215,7 @@
         ClockRegistryModule.class,
         CommunalModule.class,
         CommonDataLayerModule.class,
+        ComposeModule.class,
         ConfigurationModule.class,
         ConfigurationRepositoryModule.class,
         CommonUsageStatsDataLayerModule.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 e5acb82..d464200 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
@@ -20,9 +20,9 @@
 import android.hardware.display.DisplayManager
 import android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED
 import android.hardware.display.DisplayManager.DisplayListener
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_ADDED
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
-import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
+import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_ADDED
+import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_CHANGED
+import android.hardware.display.DisplayManager.EVENT_TYPE_DISPLAY_REMOVED
 import android.os.Handler
 import android.util.Log
 import android.view.Display
@@ -147,9 +147,9 @@
                 displayManager.registerDisplayListener(
                     callback,
                     backgroundHandler,
-                    EVENT_FLAG_DISPLAY_ADDED or
-                        EVENT_FLAG_DISPLAY_CHANGED or
-                        EVENT_FLAG_DISPLAY_REMOVED,
+                    EVENT_TYPE_DISPLAY_ADDED or
+                        EVENT_TYPE_DISPLAY_CHANGED or
+                        EVENT_TYPE_DISPLAY_REMOVED,
                 )
                 awaitClose { displayManager.unregisterDisplayListener(callback) }
             }
@@ -279,7 +279,7 @@
                     callback,
                     backgroundHandler,
                     /* eventFlags */ 0,
-                    DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_CONNECTION_CHANGED,
+                    DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED,
                 )
                 awaitClose { displayManager.unregisterDisplayListener(callback) }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 571b37f..0b2b368 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -48,12 +48,12 @@
 
 import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
 import com.android.compose.animation.scene.SceneKey;
-import com.android.dream.lowlight.dagger.LowLightDreamModule;
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.policy.PhoneWindow;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Flags;
 import com.android.systemui.ambient.touch.TouchHandler;
 import com.android.systemui.ambient.touch.TouchMonitor;
 import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent;
@@ -66,6 +66,7 @@
 import com.android.systemui.complication.dagger.ComplicationComponent;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.complication.dagger.DreamComplicationComponent;
+import com.android.systemui.dreams.dagger.DreamModule;
 import com.android.systemui.dreams.dagger.DreamOverlayComponent;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.navigationbar.gestural.domain.GestureInteractor;
@@ -210,6 +211,7 @@
                 mCommunalVisible = communalVisible;
 
                 updateLifecycleStateLocked();
+                updateGestureBlockingLocked();
             });
         }
     };
@@ -389,7 +391,7 @@
             SystemDialogsCloser systemDialogsCloser,
             UiEventLogger uiEventLogger,
             @Named(DREAM_TOUCH_INSET_MANAGER) TouchInsetManager touchInsetManager,
-            @Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
+            @Nullable @Named(DreamModule.LOW_LIGHT_DREAM_SERVICE)
             ComponentName lowLightDreamComponent,
             @Nullable @Named(HOME_CONTROL_PANEL_DREAM_COMPONENT)
             ComponentName homeControlPanelDreamComponent,
@@ -585,7 +587,8 @@
 
     private void updateGestureBlockingLocked() {
         final boolean shouldBlock = mStarted && !mShadeExpanded && !mBouncerShowing
-                && !isDreamInPreviewMode();
+                && !isDreamInPreviewMode()
+                && !(Flags.glanceableHubBackAction() && mCommunalVisible);
 
         if (shouldBlock) {
             mGestureInteractor.addGestureBlockedMatcher(DREAM_TYPE_MATCHER,
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 216cb86..faab31e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -17,14 +17,16 @@
 package com.android.systemui.dreams.dagger;
 
 import android.annotation.Nullable;
+import android.app.DreamManager;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 
-import com.android.dream.lowlight.dagger.LowLightDreamModule;
+import com.android.dream.lowlight.dagger.LowLightDreamComponent;
 import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.Flags;
 import com.android.systemui.ambient.touch.scrim.dagger.ScrimModule;
 import com.android.systemui.complication.dagger.RegisteredComplicationsModule;
 import com.android.systemui.dagger.SysUISingleton;
@@ -47,12 +49,14 @@
 import com.android.systemui.touch.TouchInsetManager;
 
 import dagger.Binds;
+import dagger.BindsOptionalOf;
 import dagger.Module;
 import dagger.Provides;
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
 import dagger.multibindings.StringKey;
 
+import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.Executor;
 
@@ -63,7 +67,6 @@
  */
 @Module(includes = {
         RegisteredComplicationsModule.class,
-        LowLightDreamModule.class,
         ScrimModule.class,
         HomeControlsDataSourceModule.class,
 },
@@ -71,6 +74,7 @@
                 DreamComplicationComponent.class,
                 DreamOverlayComponent.class,
                 HomeControlsRemoteServiceComponent.class,
+                LowLightDreamComponent.class,
         })
 public interface DreamModule {
     String DREAM_ONLY_ENABLED_FOR_DOCK_USER = "dream_only_enabled_for_dock_user";
@@ -81,6 +85,9 @@
     String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
     String HOME_CONTROL_PANEL_DREAM_COMPONENT = "home_control_panel_dream_component";
     String DREAM_TILE_SPEC = "dream";
+    String LOW_LIGHT_DREAM_SERVICE = "low_light_dream_component";
+
+    String LOW_LIGHT_CLOCK_DREAM = "low_light_clock_dream";
 
     /**
      * Provides the dream component
@@ -214,4 +221,49 @@
                 QSTilePolicy.NoRestrictions.INSTANCE
                 );
     }
+
+    /**
+     * Provides dream manager.
+     */
+    @Provides
+    static DreamManager providesDreamManager(Context context) {
+        return Objects.requireNonNull(context.getSystemService(DreamManager.class));
+    }
+
+    /**
+     * Binds a default (unset) clock dream.
+     */
+    @BindsOptionalOf
+    @Named(LOW_LIGHT_CLOCK_DREAM)
+    ComponentName bindsLowLightClockDream();
+
+    /**
+     * Provides the component name of the low light dream, or null if not configured.
+     */
+    @Provides
+    @Nullable
+    @Named(LOW_LIGHT_DREAM_SERVICE)
+    static ComponentName providesLowLightDreamService(Context context,
+            @Named(LOW_LIGHT_CLOCK_DREAM) Optional<ComponentName> clockDream) {
+        if (Flags.lowLightClockDream() && clockDream.isPresent()) {
+            return clockDream.get();
+        }
+
+        String lowLightDreamComponent = context.getResources().getString(
+                R.string.config_lowLightDreamComponent
+        );
+        return lowLightDreamComponent.isEmpty()
+                ? null : ComponentName.unflattenFromString(lowLightDreamComponent);
+    }
+
+    /**
+     * Provides Dagger component for low light dependencies.
+     */
+    @Provides
+    @SysUISingleton
+    static LowLightDreamComponent providesLowLightDreamComponent(
+            LowLightDreamComponent.Factory factory, DreamManager dreamManager,
+            @Named(LOW_LIGHT_DREAM_SERVICE) ComponentName lowLightDreamService) {
+        return factory.create(dreamManager, lowLightDreamService);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index e264635..21002c6 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.education.domain.interactor
 
 import android.os.SystemProperties
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.CoreStartable
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.contextualeducation.GestureType
@@ -56,7 +57,6 @@
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.merge
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** Allow listening to new contextual education triggered */
 @SysUISingleton
@@ -278,7 +278,8 @@
         }
 
     private suspend fun hasInitialDelayElapsed(deviceType: DeviceType): Boolean {
-        val oobeLaunchTime = tutorialRepository.launchTime(deviceType) ?: return false
+        val oobeLaunchTime =
+            tutorialRepository.getScheduledTutorialLaunchTime(deviceType) ?: return false
         return clock
             .instant()
             .isAfter(oobeLaunchTime.plusSeconds(initialDelayDuration.inWholeSeconds))
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 3cc184d..63ac783 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -31,7 +31,6 @@
 import com.android.systemui.Flags.statusBarScreenSharingChips
 import com.android.systemui.Flags.statusBarUseReposForCallChip
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.shared.flag.DualShade
 import com.android.systemui.statusbar.notification.collection.SortBySectionTimeFlag
@@ -64,9 +63,6 @@
         // SceneContainer dependencies
         SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta }
 
-        // CommunalHub dependencies
-        communalHub dependsOn MigrateClocksToBlueprint.token
-
         // DualShade dependencies
         DualShade.token dependsOn SceneContainerFlag.getMainAconfigFlag()
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index fe9c9cb..c039e01 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -100,10 +100,6 @@
     // TODO(b/242908637): Tracking Bug
     @JvmField val WALLPAPER_FULLSCREEN_PREVIEW = releasedFlag("wallpaper_fullscreen_preview")
 
-    /** Whether the long-press gesture to open wallpaper picker is enabled. */
-    // TODO(b/266242192): Tracking Bug
-    @JvmField val LOCK_SCREEN_LONG_PRESS_ENABLED = releasedFlag("lock_screen_long_press_enabled")
-
     /** Inflate and bind views upon emitting a blueprint value . */
     // TODO(b/297365780): Tracking Bug
     @JvmField val LAZY_INFLATE_KEYGUARD = releasedFlag("lazy_inflate_keyguard")
@@ -335,11 +331,6 @@
 
     // 2900 - Zero Jank fixes. Naming convention is: zj_<bug number>_<cuj name>
 
-    // TODO:(b/285623104): Tracking bug
-    @JvmField
-    val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD =
-        releasedFlag("zj_285570694_lockscreen_transition_from_aod")
-
     // TODO(b/283447257): Tracking bug
     @JvmField
     val BIGPICTURE_NOTIFICATION_LAZY_LOADING =
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
index eaf5eac..73968da 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -126,24 +126,24 @@
 }
 
 class ServerFlagReaderFake : ServerFlagReader {
-    private val flagMap: MutableMap<String, Boolean> = mutableMapOf()
+    private val flagMap: MutableMap<Pair<String, String>, Boolean> = mutableMapOf()
     private val listeners =
         mutableListOf<Pair<ServerFlagReader.ChangeListener, Collection<Flag<*>>>>()
 
     override fun hasOverride(namespace: String, name: String): Boolean {
-        return flagMap.containsKey(name)
+        return flagMap.containsKey(namespace to name)
     }
 
     override fun readServerOverride(namespace: String, name: String, default: Boolean): Boolean {
-        return flagMap.getOrDefault(name, default)
+        return flagMap.getOrDefault(namespace to name, default)
     }
 
     fun setFlagValue(namespace: String, name: String, value: Boolean) {
-        flagMap.put(name, value)
+        flagMap.put(namespace to name, value)
 
         for ((listener, flags) in listeners) {
             flagLoop@ for (flag in flags) {
-                if (name == flag.name) {
+                if (namespace == flag.namespace && name == flag.name) {
                     listener.onChange(flag, if (value) "true" else "false")
                     break@flagLoop
                 }
@@ -152,13 +152,13 @@
     }
 
     fun eraseFlag(namespace: String, name: String) {
-        flagMap.remove(name)
+        flagMap.remove(namespace to name)
     }
 
     override fun listenForChanges(
         flags: Collection<Flag<*>>,
         listener: ServerFlagReader.ChangeListener
     ) {
-        listeners.add(Pair(listener, flags))
+        listeners.add(listener to flags)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt b/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
index 316964a..84c4bdf 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/msdl/qs/TileHapticsViewModel.kt
@@ -19,6 +19,7 @@
 import android.service.quicksettings.Tile
 import com.android.systemui.Flags
 import com.android.systemui.animation.Expandable
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.ExclusiveActivatable
 import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
 import com.android.systemui.util.kotlin.pairwise
@@ -173,6 +174,7 @@
     }
 }
 
+@SysUISingleton
 class TileHapticsViewModelFactoryProvider
 @Inject
 constructor(private val tileHapticsViewModelFactory: TileHapticsViewModel.Factory) {
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/DeviceSchedulerInfo.kt
similarity index 85%
rename from packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
rename to packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/DeviceSchedulerInfo.kt
index 1dbe83a..c436ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/TutorialSchedulerInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/model/DeviceSchedulerInfo.kt
@@ -20,14 +20,17 @@
 
 data class DeviceSchedulerInfo(
     var launchTime: Instant? = null,
-    var firstConnectionTime: Instant? = null
+    var firstConnectionTime: Instant? = null,
+    var isNotified: Boolean = false,
 ) {
     constructor(
         launchTimeSec: Long?,
-        firstConnectionTimeSec: Long?
+        firstConnectionTimeSec: Long?,
+        isNotified: Boolean = false,
     ) : this(
         launchTimeSec?.let { Instant.ofEpochSecond(it) },
-        firstConnectionTimeSec?.let { Instant.ofEpochSecond(it) }
+        firstConnectionTimeSec?.let { Instant.ofEpochSecond(it) },
+        isNotified,
     )
 
     val wasEverConnected: Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
index a89ec70..526e7db 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/data/repository/TutorialSchedulerRepository.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import androidx.datastore.core.DataStore
 import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.booleanPreferencesKey
 import androidx.datastore.preferences.core.edit
 import androidx.datastore.preferences.core.longPreferencesKey
 import androidx.datastore.preferences.preferencesDataStore
@@ -47,28 +48,36 @@
     private val Context.dataStore: DataStore<Preferences> by
         preferencesDataStore(name = dataStoreName, scope = backgroundScope)
 
-    suspend fun isLaunched(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isLaunched
+    suspend fun setScheduledTutorialLaunchTime(device: DeviceType, time: Instant) {
+        applicationContext.dataStore.edit { pref -> pref[getLaunchKey(device)] = time.epochSecond }
+    }
 
-    suspend fun launchTime(deviceType: DeviceType): Instant? = loadData()[deviceType]!!.launchTime
+    suspend fun isScheduledTutorialLaunched(deviceType: DeviceType): Boolean =
+        loadData()[deviceType]!!.isLaunched
+
+    suspend fun getScheduledTutorialLaunchTime(deviceType: DeviceType): Instant? =
+        loadData()[deviceType]!!.launchTime
+
+    suspend fun setFirstConnectionTime(device: DeviceType, time: Instant) {
+        applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time.epochSecond }
+    }
+
+    suspend fun setNotified(device: DeviceType) {
+        applicationContext.dataStore.edit { pref -> pref[getNotificationKey(device)] = true }
+    }
+
+    suspend fun isNotified(deviceType: DeviceType): Boolean = loadData()[deviceType]!!.isNotified
 
     suspend fun wasEverConnected(deviceType: DeviceType): Boolean =
         loadData()[deviceType]!!.wasEverConnected
 
-    suspend fun firstConnectionTime(deviceType: DeviceType): Instant? =
+    suspend fun getFirstConnectionTime(deviceType: DeviceType): Instant? =
         loadData()[deviceType]!!.firstConnectionTime
 
     private suspend fun loadData(): Map<DeviceType, DeviceSchedulerInfo> {
         return applicationContext.dataStore.data.map { pref -> getSchedulerInfo(pref) }.first()
     }
 
-    suspend fun updateFirstConnectionTime(device: DeviceType, time: Instant) {
-        applicationContext.dataStore.edit { pref -> pref[getConnectKey(device)] = time.epochSecond }
-    }
-
-    suspend fun updateLaunchTime(device: DeviceType, time: Instant) {
-        applicationContext.dataStore.edit { pref -> pref[getLaunchKey(device)] = time.epochSecond }
-    }
-
     private fun getSchedulerInfo(pref: Preferences): Map<DeviceType, DeviceSchedulerInfo> {
         return mapOf(
             DeviceType.KEYBOARD to getDeviceSchedulerInfo(pref, DeviceType.KEYBOARD),
@@ -79,7 +88,8 @@
     private fun getDeviceSchedulerInfo(pref: Preferences, device: DeviceType): DeviceSchedulerInfo {
         val launchTime = pref[getLaunchKey(device)]
         val connectionTime = pref[getConnectKey(device)]
-        return DeviceSchedulerInfo(launchTime, connectionTime)
+        val isNotified = pref[getNotificationKey(device)] == true
+        return DeviceSchedulerInfo(launchTime, connectionTime, isNotified)
     }
 
     private fun getLaunchKey(device: DeviceType) =
@@ -88,6 +98,9 @@
     private fun getConnectKey(device: DeviceType) =
         longPreferencesKey(device.name + CONNECT_TIME_SUFFIX)
 
+    private fun getNotificationKey(device: DeviceType) =
+        booleanPreferencesKey(device.name + NOTIFIED_SUFFIX)
+
     suspend fun clear() {
         applicationContext.dataStore.edit { it.clear() }
     }
@@ -96,6 +109,7 @@
         const val DATASTORE_NAME = "TutorialScheduler"
         const val LAUNCH_TIME_SUFFIX = "_LAUNCH_TIME"
         const val CONNECT_TIME_SUFFIX = "_CONNECT_TIME"
+        const val NOTIFIED_SUFFIX = "_NOTIFIED"
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index 7758dcc..419eefe 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -17,8 +17,8 @@
 package com.android.systemui.inputdevice.tutorial.domain.interactor
 
 import android.os.SystemProperties
-import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
 import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
@@ -35,6 +35,7 @@
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.hours
 import kotlin.time.toKotlinDuration
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -43,6 +44,7 @@
 import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 
 /**
@@ -58,6 +60,7 @@
     private val repo: TutorialSchedulerRepository,
     private val logger: InputDeviceTutorialLogger,
     commandRegistry: CommandRegistry,
+    @Background private val backgroundScope: CoroutineScope,
 ) {
     init {
         commandRegistry.registerCommand(COMMAND) { TutorialCommand() }
@@ -70,14 +73,14 @@
         )
 
     private val touchpadScheduleFlow = flow {
-        if (!repo.isLaunched(TOUCHPAD)) {
+        if (!repo.isNotified(TOUCHPAD)) {
             schedule(TOUCHPAD)
             emit(TOUCHPAD)
         }
     }
 
     private val keyboardScheduleFlow = flow {
-        if (!repo.isLaunched(KEYBOARD)) {
+        if (!repo.isNotified(KEYBOARD)) {
             schedule(KEYBOARD)
             emit(KEYBOARD)
         }
@@ -88,9 +91,9 @@
             logger.d("Waiting for $deviceType to connect")
             waitForDeviceConnection(deviceType)
             logger.logDeviceFirstConnection(deviceType)
-            repo.updateFirstConnectionTime(deviceType, Instant.now())
+            repo.setFirstConnectionTime(deviceType, Instant.now())
         }
-        val remainingTime = remainingTime(start = repo.firstConnectionTime(deviceType)!!)
+        val remainingTime = remainingTime(start = repo.getFirstConnectionTime(deviceType)!!)
         logger.d("Tutorial is scheduled in ${remainingTime.inWholeSeconds} seconds")
         delay(remainingTime)
         waitForDeviceConnection(deviceType)
@@ -100,18 +103,17 @@
         isAnyDeviceConnected[deviceType]!!.filter { it }.first()
 
     // Only for testing notifications. This should behave independently from scheduling
-    @VisibleForTesting val commandTutorials = MutableStateFlow(TutorialType.NONE)
+    val commandTutorials = MutableStateFlow(TutorialType.NONE)
 
     // Merging two flows ensures that tutorial is launched consecutively to avoid race condition
     val tutorials: Flow<TutorialType> =
         merge(touchpadScheduleFlow, keyboardScheduleFlow).map {
             val tutorialType = resolveTutorialType(it)
 
-            // TODO: notifying time is not oobe launching time - move these updates into oobe
             if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
-                repo.updateLaunchTime(KEYBOARD, Instant.now())
+                repo.setNotified(KEYBOARD)
             if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
-                repo.updateLaunchTime(TOUCHPAD, Instant.now())
+                repo.setNotified(TOUCHPAD)
 
             logger.logTutorialLaunched(tutorialType)
             tutorialType
@@ -121,10 +123,10 @@
         // Resolve the type of tutorial depending on which device are connected when the tutorial is
         // launched. E.g. when the keyboard is connected for [LAUNCH_DELAY], both keyboard and
         // touchpad are connected, we launch the tutorial for both.
-        if (repo.isLaunched(deviceType)) return TutorialType.NONE
+        if (repo.isNotified(deviceType)) return TutorialType.NONE
         val otherDevice = if (deviceType == KEYBOARD) TOUCHPAD else KEYBOARD
         val isOtherDeviceConnected = isAnyDeviceConnected[otherDevice]!!.first()
-        if (!repo.isLaunched(otherDevice) && isOtherDeviceConnected) return TutorialType.BOTH
+        if (!repo.isNotified(otherDevice) && isOtherDeviceConnected) return TutorialType.BOTH
         return if (deviceType == KEYBOARD) TutorialType.KEYBOARD else TutorialType.TOUCHPAD
     }
 
@@ -133,6 +135,15 @@
         return LAUNCH_DELAY.minus(elapsed).toKotlinDuration()
     }
 
+    fun updateLaunchInfo(tutorialType: TutorialType) {
+        backgroundScope.launch {
+            if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
+                repo.setScheduledTutorialLaunchTime(KEYBOARD, Instant.now())
+            if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
+                repo.setScheduledTutorialLaunchTime(TOUCHPAD, Instant.now())
+        }
+    }
+
     inner class TutorialCommand : Command {
         override fun execute(pw: PrintWriter, args: List<String>) {
             if (args.isEmpty()) {
@@ -147,10 +158,20 @@
                     }
                 "info" ->
                     runBlocking {
-                        pw.println("Keyboard connect time = ${repo.firstConnectionTime(KEYBOARD)}")
-                        pw.println("         launch time = ${repo.launchTime(KEYBOARD)}")
-                        pw.println("Touchpad connect time = ${repo.firstConnectionTime(TOUCHPAD)}")
-                        pw.println("         launch time = ${repo.launchTime(TOUCHPAD)}")
+                        pw.println(
+                            "Keyboard connect time = ${repo.getFirstConnectionTime(KEYBOARD)}"
+                        )
+                        pw.println("         notified = ${repo.isNotified(KEYBOARD)}")
+                        pw.println(
+                            "         launch time = ${repo.getScheduledTutorialLaunchTime(KEYBOARD)}"
+                        )
+                        pw.println(
+                            "Touchpad connect time = ${repo.getFirstConnectionTime(TOUCHPAD)}"
+                        )
+                        pw.println("         notified = ${repo.isNotified(TOUCHPAD)}")
+                        pw.println(
+                            "         launch time = ${repo.getScheduledTutorialLaunchTime(TOUCHPAD)}"
+                        )
                     }
                 "notify" -> {
                     if (args.size != 2) help(pw)
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
index 67b307f..639e9b1 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -33,6 +33,8 @@
 import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger.TutorialContext
 import com.android.systemui.inputdevice.tutorial.KeyboardTouchpadTutorialMetricsLogger
 import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.TutorialType
 import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen
 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel
 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel.Factory.ViewModelFactoryAssistedProvider
@@ -51,6 +53,7 @@
 constructor(
     private val viewModelFactoryAssistedProvider: ViewModelFactoryAssistedProvider,
     private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>,
+    private val schedulerInteractor: TutorialSchedulerInteractor,
     private val logger: InputDeviceTutorialLogger,
     private val metricsLogger: KeyboardTouchpadTutorialMetricsLogger,
 ) : ComponentActivity() {
@@ -93,15 +96,28 @@
         setContent {
             PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) }
         }
-        // TODO(b/376692701): Update launchTime when the activity is launched by Companion App
         if (savedInstanceState == null) {
-            metricsLogger.logPeripheralTutorialLaunched(
-                intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY),
-                intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY),
-            )
             logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL)
+
+            val entryPointExtra = intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY)
+            val tutorialTypeExtra = intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY)
+            metricsLogger.logPeripheralTutorialLaunched(entryPointExtra, tutorialTypeExtra)
+            // We only update launched info when the tutorial is triggered by the scheduler
+            if (entryPointExtra.equals(INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER))
+                updateLaunchInfo(tutorialTypeExtra)
         }
     }
+
+    private fun updateLaunchInfo(tutorialTypeExtra: String?) {
+        val type =
+            when (tutorialTypeExtra) {
+                INTENT_TUTORIAL_SCOPE_KEYBOARD -> TutorialType.KEYBOARD
+                INTENT_TUTORIAL_SCOPE_TOUCHPAD -> TutorialType.TOUCHPAD
+                INTENT_TUTORIAL_SCOPE_ALL -> TutorialType.BOTH
+                else -> TutorialType.NONE
+            }
+        schedulerInteractor.updateLaunchInfo(type)
+    }
 }
 
 @Composable
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index f549e64..644deb0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -39,7 +39,6 @@
 import androidx.core.math.MathUtils
 import com.android.app.animation.Interpolators
 import com.android.internal.R
-import com.android.keyguard.KeyguardClockSwitchController
 import com.android.keyguard.KeyguardViewController
 import com.android.systemui.Flags.fasterUnlockTransition
 import com.android.systemui.dagger.SysUISingleton
@@ -171,7 +170,7 @@
     private val notificationShadeWindowController: NotificationShadeWindowController,
     private val powerManager: PowerManager,
     private val wallpaperManager: WallpaperManager,
-    private val deviceStateManager: DeviceStateManager
+    private val deviceStateManager: DeviceStateManager,
 ) : KeyguardStateController.Callback, ISysuiUnlockAnimationController.Stub() {
 
     interface KeyguardUnlockAnimationListener {
@@ -195,7 +194,7 @@
             playingCannedAnimation: Boolean,
             isWakeAndUnlockNotFromDream: Boolean,
             unlockAnimationStartDelay: Long,
-            unlockAnimationDuration: Long
+            unlockAnimationDuration: Long,
         ) {}
 
         /**
@@ -206,7 +205,7 @@
         fun onUnlockAnimationFinished() {}
     }
 
-    /** The SmartSpace view on the lockscreen, provided by [KeyguardClockSwitchController]. */
+    /** The SmartSpace view on the lockscreen. */
     var lockscreenSmartspace: View? = null
 
     /**
@@ -251,7 +250,7 @@
      */
     override fun setLauncherUnlockController(
         activityClass: String,
-        callback: ILauncherUnlockAnimationController?
+        callback: ILauncherUnlockAnimationController?,
     ) {
         launcherActivityClass = activityClass
         launcherUnlockController = callback
@@ -371,7 +370,7 @@
                             Log.d(
                                 TAG,
                                 "skip finishSurfaceBehindRemoteAnimation" +
-                                    " surfaceBehindAlpha=$surfaceBehindAlpha"
+                                    " surfaceBehindAlpha=$surfaceBehindAlpha",
                             )
                         }
                     }
@@ -388,7 +387,7 @@
             addUpdateListener { valueAnimator: ValueAnimator ->
                 setWallpaperAppearAmount(
                     valueAnimator.animatedValue as Float,
-                    openingWallpaperTargets
+                    openingWallpaperTargets,
                 )
             }
             addListener(
@@ -419,7 +418,7 @@
                 addUpdateListener { valueAnimator: ValueAnimator ->
                     setWallpaperAppearAmount(
                         valueAnimator.animatedValue as Float,
-                        closingWallpaperTargets
+                        closingWallpaperTargets,
                     )
                 }
             }
@@ -489,7 +488,7 @@
         Log.wtf(
             TAG,
             "  !notificationShadeWindowController.isLaunchingActivity: " +
-                "${!notificationShadeWindowController.isLaunchingActivity}"
+                "${!notificationShadeWindowController.isLaunchingActivity}",
         )
         Log.wtf(TAG, "  launcherUnlockController != null: ${launcherUnlockController != null}")
         Log.wtf(TAG, "  !isFoldable(context): ${!isDeviceFoldable(resources, deviceStateManager)}")
@@ -517,7 +516,7 @@
             try {
                 launcherUnlockController?.setUnlockAmount(
                     1f,
-                    biometricUnlockControllerLazy.get().isWakeAndUnlock /* forceIfAnimating */
+                    biometricUnlockControllerLazy.get().isWakeAndUnlock, /* forceIfAnimating */
                 )
             } catch (e: DeadObjectException) {
                 Log.e(
@@ -525,7 +524,7 @@
                     "launcherUnlockAnimationController was dead, but non-null in " +
                         "onKeyguardGoingAwayChanged(). Catching exception as this should mean " +
                         "Launcher is in the process of being destroyed, but the IPC to System UI " +
-                        "telling us hasn't arrived yet."
+                        "telling us hasn't arrived yet.",
                 )
             }
         }
@@ -570,7 +569,7 @@
                     offset(
                         0,
                         (lockscreenSmartspace as? BcSmartspaceDataPlugin.SmartspaceView)
-                            ?.currentCardTopPadding ?: 0
+                            ?.currentCardTopPadding ?: 0,
                     )
                 }
         }
@@ -584,7 +583,7 @@
             launcherUnlockController?.prepareForUnlock(
                 willUnlockWithSmartspaceTransition, /* willAnimateSmartspace */
                 lockscreenSmartspaceBounds, /* lockscreenSmartspaceBounds */
-                selectedPage /* selectedPage */
+                selectedPage, /* selectedPage */
             )
 
             launcherPreparedForUnlock = true
@@ -612,7 +611,7 @@
         openingWallpapers: Array<RemoteAnimationTarget>,
         closingWallpapers: Array<RemoteAnimationTarget>,
         startTime: Long,
-        requestedShowSurfaceBehindKeyguard: Boolean
+        requestedShowSurfaceBehindKeyguard: Boolean,
     ) {
         if (surfaceTransactionApplier == null) {
             surfaceTransactionApplier =
@@ -651,7 +650,7 @@
                     launcherUnlockController?.playUnlockAnimation(
                         true,
                         unlockAnimationDurationMs() + cannedUnlockStartDelayMs(),
-                        0 /* startDelay */
+                        0, /* startDelay */
                     )
                 } catch (e: DeadObjectException) {
                     // Hello! If you are here investigating a bug where Launcher is blank (no icons)
@@ -664,7 +663,7 @@
                         "launcherUnlockAnimationController was dead, but non-null. " +
                             "Catching exception as this should mean Launcher is in the process " +
                             "of being destroyed, but the IPC to System UI telling us hasn't " +
-                            "arrived yet."
+                            "arrived yet.",
                     )
                 }
 
@@ -690,7 +689,7 @@
                 playingCannedUnlockAnimation /* playingCannedAnimation */,
                 isWakeAndUnlockNotFromDream /* isWakeAndUnlockNotFromDream */,
                 cannedUnlockStartDelayMs() /* unlockStartDelay */,
-                LAUNCHER_ICONS_ANIMATION_DURATION_MS /* unlockAnimationDuration */
+                LAUNCHER_ICONS_ANIMATION_DURATION_MS, /* unlockAnimationDuration */
             )
         }
 
@@ -743,7 +742,7 @@
             Log.wtf(
                 TAG,
                 "Launcher is prepared for unlock, so we should have started the " +
-                    "in-window animation, however we apparently did not."
+                    "in-window animation, however we apparently did not.",
             )
             logInWindowAnimationConditions()
         }
@@ -763,7 +762,7 @@
             launcherUnlockController?.playUnlockAnimation(
                 true /* unlocked */,
                 LAUNCHER_ICONS_ANIMATION_DURATION_MS /* duration */,
-                cannedUnlockStartDelayMs() /* startDelay */
+                cannedUnlockStartDelayMs(), /* startDelay */
             )
         } catch (e: DeadObjectException) {
             // Hello! If you are here investigating a bug where Launcher is blank (no icons)
@@ -776,7 +775,7 @@
                 "launcherUnlockAnimationController was dead, but non-null. " +
                     "Catching exception as this should mean Launcher is in the process " +
                     "of being destroyed, but the IPC to System UI telling us hasn't " +
-                    "arrived yet."
+                    "arrived yet.",
             )
         }
 
@@ -806,7 +805,7 @@
                     Log.e(
                         TAG,
                         "Finish keyguard exit animation delayed Runnable ran, but we are " +
-                            "showing and not going away."
+                            "showing and not going away.",
                     )
                     return@postDelayed
                 }
@@ -820,7 +819,7 @@
                         .exitKeyguardAndFinishSurfaceBehindRemoteAnimation(false /* cancelled */)
                 }
             },
-            cannedUnlockStartDelayMs()
+            cannedUnlockStartDelayMs(),
         )
     }
 
@@ -999,7 +998,7 @@
                 surfaceBehindMatrix.setTranslate(
                     surfaceBehindRemoteAnimationTarget.screenSpaceBounds.left.toFloat(),
                     surfaceBehindRemoteAnimationTarget.screenSpaceBounds.top.toFloat() +
-                        surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount)
+                        surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount),
                 )
 
                 // Scale up from a point at the center-bottom of the surface.
@@ -1007,7 +1006,7 @@
                     scaleFactor,
                     scaleFactor,
                     keyguardViewController.viewRootImpl.width / 2f,
-                    surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y
+                    surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y,
                 )
 
                 // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is
@@ -1142,14 +1141,14 @@
             if (!KeyguardWmStateRefactor.isEnabled) {
                 keyguardViewController.hide(
                     surfaceBehindRemoteAnimationStartTime,
-                    0 /* fadeOutDuration */
+                    0, /* fadeOutDuration */
                 )
             }
         } else {
             Log.i(
                 TAG,
                 "#hideKeyguardViewAfterRemoteAnimation called when keyguard view is not " +
-                    "showing. Ignoring..."
+                    "showing. Ignoring...",
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index e8eb497..5e0768a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -18,19 +18,7 @@
 package com.android.systemui.keyguard
 
 import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.ComposeView
-import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
-import com.android.compose.animation.scene.SceneKey
-import com.android.compose.animation.scene.SceneTransitionLayout
 import com.android.internal.jank.InteractionJankMonitor
-import com.android.keyguard.KeyguardStatusView
-import com.android.keyguard.KeyguardStatusViewController
-import com.android.keyguard.dagger.KeyguardStatusViewComponent
 import com.android.systemui.CoreStartable
 import com.android.systemui.Flags.lightRevealMigration
 import com.android.systemui.biometrics.ui.binder.DeviceEntryUnlockTrackerViewBinder
@@ -39,12 +27,9 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
-import com.android.systemui.keyguard.shared.model.LockscreenSceneBlueprint
 import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder
 import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder
-import com.android.systemui.keyguard.ui.composable.LockscreenContent
-import com.android.systemui.keyguard.ui.composable.blueprint.ComposableLockscreenSceneBlueprint
 import com.android.systemui.keyguard.ui.view.KeyguardIndicationArea
 import com.android.systemui.keyguard.ui.view.KeyguardRootView
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBlueprintViewModel
@@ -52,23 +37,19 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardSmartspaceViewModel
 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
 import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
 import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.res.R
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.KeyguardIndicationController
 import com.android.systemui.statusbar.LightRevealScrim
 import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationLockscreenScrimViewModel
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import com.android.systemui.wallpapers.ui.viewmodel.WallpaperViewModel
 import com.google.android.msdl.domain.MSDLPlayer
-import dagger.Lazy
 import java.util.Optional
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -87,7 +68,6 @@
     private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
     private val chipbarCoordinator: ChipbarCoordinator,
     private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
-    private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
     @ShadeDisplayAware private val configuration: ConfigurationState,
     @ShadeDisplayAware private val context: Context,
     private val keyguardIndicationController: KeyguardIndicationController,
@@ -98,9 +78,6 @@
     private val falsingManager: FalsingManager,
     private val keyguardClockViewModel: KeyguardClockViewModel,
     private val smartspaceViewModel: KeyguardSmartspaceViewModel,
-    private val lockscreenContentViewModelFactory: LockscreenContentViewModel.Factory,
-    private val notificationScrimViewModelFactory: NotificationLockscreenScrimViewModel.Factory,
-    private val lockscreenSceneBlueprintsLazy: Lazy<Set<LockscreenSceneBlueprint>>,
     private val clockInteractor: KeyguardClockInteractor,
     private val keyguardViewMediator: KeyguardViewMediator,
     private val deviceEntryUnlockTrackerViewBinder: Optional<DeviceEntryUnlockTrackerViewBinder>,
@@ -113,24 +90,6 @@
 ) : CoreStartable {
 
     private var rootViewHandle: DisposableHandle? = null
-    private var indicationAreaHandle: DisposableHandle? = null
-
-    var keyguardStatusViewController: KeyguardStatusViewController? = null
-        get() {
-            if (field == null) {
-                val statusViewComponent =
-                    keyguardStatusViewComponentFactory.build(
-                        LayoutInflater.from(context).inflate(R.layout.keyguard_status_view, null)
-                            as KeyguardStatusView,
-                        context.display,
-                    )
-                val controller = statusViewComponent.keyguardStatusViewController
-                controller.init()
-                field = controller
-            }
-
-            return field
-        }
 
     override fun start() {
         bindKeyguardRootView()
@@ -192,42 +151,5 @@
             )
     }
 
-    private fun createLockscreen(
-        context: Context,
-        viewModelFactory: LockscreenContentViewModel.Factory,
-        notificationScrimViewModelFactory: NotificationLockscreenScrimViewModel.Factory,
-        blueprints: Set<@JvmSuppressWildcards LockscreenSceneBlueprint>,
-    ): View {
-        val sceneBlueprints =
-            blueprints.mapNotNull { it as? ComposableLockscreenSceneBlueprint }.toSet()
-        return ComposeView(context).apply {
-            setContent {
-                // STL is used solely to provide a SceneScope to enable us to invoke SceneScope
-                // composables.
-                val currentScene = remember { SceneKey("root-view-scene-key") }
-                val state = remember { MutableSceneTransitionLayoutState(currentScene) }
-                SceneTransitionLayout(state) {
-                    scene(currentScene) {
-                        with(
-                            LockscreenContent(
-                                viewModelFactory = viewModelFactory,
-                                notificationScrimViewModelFactory =
-                                    notificationScrimViewModelFactory,
-                                blueprints = sceneBlueprints,
-                                clockInteractor = clockInteractor,
-                            )
-                        ) {
-                            Content(modifier = Modifier.fillMaxSize())
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Temporary, to allow NotificationPanelViewController to use the same instance while code is
-     * migrated: b/288242803
-     */
     fun getKeyguardRootView() = keyguardRootView
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 9f13160..63ac509 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -4058,7 +4058,8 @@
                 RemoteAnimationTarget[] nonApps,
                 IRemoteAnimationFinishedCallback finishedCallback)
                 throws RemoteException {
-            mRunner = mActivityTransitionAnimator.get().createRunner(mActivityLaunchController);
+            mRunner = mActivityTransitionAnimator.get()
+                    .createEphemeralRunner(mActivityLaunchController);
             mRunner.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/MigrateClocksToBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/MigrateClocksToBlueprint.kt
deleted file mode 100644
index 5a2943b..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/MigrateClocksToBlueprint.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.keyguard
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the migrate clocks to blueprint flag. */
-@Suppress("NOTHING_TO_INLINE")
-object MigrateClocksToBlueprint {
-    /** The aconfig flag name */
-    const val FLAG_NAME = Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
-
-    /** A token used for dependency declaration */
-    val token: FlagToken
-        get() = FlagToken(FLAG_NAME, isEnabled)
-
-    /** Is the refactor enabled */
-    @JvmStatic
-    inline val isEnabled
-        get() = Flags.migrateClocksToBlueprint()
-
-    /**
-     * 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/keyguard/WindowManagerOcclusionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt
index 4bac8f7..a1fb1a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt
@@ -110,7 +110,7 @@
                 apps: Array<RemoteAnimationTarget>,
                 wallpapers: Array<RemoteAnimationTarget>,
                 nonApps: Array<RemoteAnimationTarget>,
-                finishedCallback: IRemoteAnimationFinishedCallback?
+                finishedCallback: IRemoteAnimationFinishedCallback?,
             ) {
                 Log.d(TAG, "occludeAnimationRunner#onAnimationStart")
                 // Wrap the callback so that it's guaranteed to be nulled out once called.
@@ -126,7 +126,7 @@
                     taskInfo = apps.firstOrNull()?.taskInfo,
                 )
                 activityTransitionAnimator
-                    .createRunner(occludeAnimationController)
+                    .createEphemeralRunner(occludeAnimationController)
                     .onAnimationStart(
                         transit,
                         apps,
@@ -161,7 +161,7 @@
                 apps: Array<RemoteAnimationTarget>,
                 wallpapers: Array<RemoteAnimationTarget>,
                 nonApps: Array<RemoteAnimationTarget>,
-                finishedCallback: IRemoteAnimationFinishedCallback?
+                finishedCallback: IRemoteAnimationFinishedCallback?,
             ) {
                 Log.d(TAG, "unoccludeAnimationRunner#onAnimationStart")
                 // Wrap the callback so that it's guaranteed to be nulled out once called.
@@ -179,14 +179,14 @@
                 interactionJankMonitor.begin(
                     createInteractionJankMonitorConf(
                         InteractionJankMonitor.CUJ_LOCKSCREEN_OCCLUSION,
-                        "UNOCCLUDE"
+                        "UNOCCLUDE",
                     )
                 )
                 if (apps.isEmpty()) {
                     Log.d(
                         TAG,
                         "No apps provided to unocclude runner; " +
-                            "skipping animation and unoccluding."
+                            "skipping animation and unoccluding.",
                     )
                     unoccludeAnimationFinishedCallback?.onAnimationFinished()
                     return
@@ -210,7 +210,7 @@
                                     0f,
                                     (1f - animatedValue) *
                                         surfaceHeight *
-                                        UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT
+                                        UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT,
                                 )
 
                                 SurfaceParams.Builder(target.leash)
@@ -313,12 +313,12 @@
 
     private fun createInteractionJankMonitorConf(
         cuj: Int,
-        tag: String?
+        tag: String?,
     ): InteractionJankMonitor.Configuration.Builder {
         val builder =
             InteractionJankMonitor.Configuration.Builder.withView(
                 cuj,
-                keyguardViewController.get().getViewRootImpl().view
+                keyguardViewController.get().getViewRootImpl().view,
             )
         return if (tag != null) builder.setTag(tag) else builder
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 4370abf..d95a126 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -32,8 +32,6 @@
 import com.android.keyguard.dagger.KeyguardDisplayModule;
 import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.keyguard.mediator.ScreenOnCoordinator;
 import com.android.systemui.CoreStartable;
 import com.android.systemui.animation.ActivityTransitionAnimator;
@@ -107,9 +105,7 @@
 @ExperimentalCoroutinesApi
 @Module(subcomponents = {
         KeyguardQsUserSwitchComponent.class,
-        KeyguardStatusBarViewComponent.class,
-        KeyguardStatusViewComponent.class,
-        KeyguardUserSwitcherComponent.class},
+        KeyguardStatusBarViewComponent.class},
         includes = {
             DeviceEntryIconTransitionModule.class,
             FalsingModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
index 74ee052..57f06fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/CameraQuickAffordanceConfig.kt
@@ -21,13 +21,13 @@
 import android.app.admin.DevicePolicyManager
 import android.content.Context
 import android.content.pm.PackageManager
-import com.android.systemui.res.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.camera.CameraGestureHelper
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.ShadeDisplayAware
 import dagger.Lazy
@@ -65,7 +65,7 @@
                         icon =
                             Icon.Resource(
                                 R.drawable.ic_camera,
-                                ContentDescription.Resource(R.string.accessibility_camera_button)
+                                ContentDescription.Resource(R.string.accessibility_camera_button),
                             )
                     )
                 } else {
@@ -88,7 +88,7 @@
         cameraGestureHelper
             .get()
             .launchCamera(StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE)
-        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(true)
     }
 
     private suspend fun isLaunchable(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index e8d3bfa..1b8baf6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -210,16 +210,16 @@
     ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
         return if (ModesUi.isEnabled) {
             if (!isAvailable.value) {
-                KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
             } else {
                 val dnd = interactor.dndMode.value
                 if (dnd == null) {
                     Log.wtf(TAG, "Triggered DND but it's null!?")
-                    return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
                 if (dnd.isActive) {
                     interactor.deactivateMode(dnd)
-                    return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 } else {
                     if (interactor.shouldAskForZenDuration(dnd)) {
                         // NOTE: The dialog handles turning on the mode itself.
@@ -229,16 +229,16 @@
                         )
                     } else {
                         interactor.activateMode(dnd)
-                        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                     }
                 }
             }
         } else {
             when {
-                !oldIsAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                !oldIsAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 zenMode != ZEN_MODE_OFF -> {
                     controller.setZen(ZEN_MODE_OFF, null, TAG)
-                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
 
                 settingsValue == ZEN_DURATION_PROMPT ->
@@ -249,12 +249,12 @@
 
                 settingsValue == ZEN_DURATION_FOREVER -> {
                     controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG)
-                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
 
                 else -> {
                     controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG)
-                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
index 480ef5e..e2642a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/FlashlightQuickAffordanceConfig.kt
@@ -18,15 +18,14 @@
 package com.android.systemui.keyguard.data.quickaffordance
 
 import android.content.Context
-import com.android.systemui.res.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
+import com.android.systemui.res.R
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.statusbar.policy.FlashlightController
 import javax.inject.Inject
@@ -50,9 +49,9 @@
                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
                     Icon.Resource(
                         R.drawable.qs_flashlight_icon_on,
-                        ContentDescription.Resource(R.string.quick_settings_flashlight_label)
+                        ContentDescription.Resource(R.string.quick_settings_flashlight_label),
                     ),
-                    ActivationState.Active
+                    ActivationState.Active,
                 )
         }
 
@@ -61,9 +60,9 @@
                 KeyguardQuickAffordanceConfig.LockScreenState.Visible(
                     Icon.Resource(
                         R.drawable.qs_flashlight_icon_off,
-                        ContentDescription.Resource(R.string.quick_settings_flashlight_label)
+                        ContentDescription.Resource(R.string.quick_settings_flashlight_label),
                     ),
-                    ActivationState.Inactive
+                    ActivationState.Inactive,
                 )
         }
 
@@ -92,14 +91,14 @@
                             } else {
                                 FlashlightState.OffAvailable.toLockScreenState()
                             },
-                            TAG
+                            TAG,
                         )
                     }
 
                     override fun onFlashlightError() {
                         trySendWithFailureLogging(
                             FlashlightState.OffAvailable.toLockScreenState(),
-                            TAG
+                            TAG,
                         )
                     }
 
@@ -114,7 +113,7 @@
                                     FlashlightState.OffAvailable.toLockScreenState()
                                 }
                             },
-                            TAG
+                            TAG,
                         )
                     }
                 }
@@ -130,7 +129,7 @@
         flashlightController.setFlashlight(
             flashlightController.isAvailable && !flashlightController.isEnabled
         )
-        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
     }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
index d335a18..96b07cc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfig.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
 
 /** Lockscreen affordance that opens the glanceable hub. */
 @SysUISingleton
@@ -60,13 +60,13 @@
         get() = R.drawable.ic_widgets
 
     override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
-        get() = flow {
-            emit(
+        get() =
+            communalInteractor.isCommunalAvailable.map { available ->
                 if (!communalSettingsInteractor.isV2FlagEnabled()) {
                     Log.i(TAG, "Button hidden on lockscreen: flag not enabled.")
                     KeyguardQuickAffordanceConfig.LockScreenState.Hidden
-                } else if (!communalInteractor.isCommunalEnabled.value) {
-                    Log.i(TAG, "Button hidden on lockscreen: hub not enabled in settings.")
+                } else if (!available) {
+                    Log.i(TAG, "Button hidden on lockscreen: hub not available.")
                     KeyguardQuickAffordanceConfig.LockScreenState.Hidden
                 } else {
                     KeyguardQuickAffordanceConfig.LockScreenState.Visible(
@@ -77,8 +77,7 @@
                             )
                     )
                 }
-            )
-        }
+            }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
         return if (!communalSettingsInteractor.isV2FlagEnabled()) {
@@ -111,7 +110,7 @@
                 transitionKey = CommunalTransitionKeys.SimpleFade,
             )
         }
-        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(true)
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
index 1cf6183..ade65c3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceConfig.kt
@@ -21,10 +21,10 @@
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
-import com.android.systemui.res.R
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.keyguard.shared.quickaffordance.ActivationState
+import com.android.systemui.res.R
 import kotlinx.coroutines.flow.Flow
 
 /** Defines interface that can act as data source for a single quick affordance model. */
@@ -71,7 +71,7 @@
         /** The picker shows the item for selecting this affordance as it normally would. */
         data class Default(
             /** Optional [Intent] to use to start an activity to configure this affordance. */
-            val configureIntent: Intent? = null,
+            val configureIntent: Intent? = null
         ) : PickerScreenState()
 
         /**
@@ -134,34 +134,39 @@
         ) : LockScreenState()
     }
 
-    sealed class OnTriggeredResult {
+    sealed class OnTriggeredResult() {
         /**
          * Returning this as a result from the [onTriggered] method means that the implementation
          * has taken care of the action, the system will do nothing.
+         *
+         * @param[actionLaunched] Whether the implementation handled the action by launching a
+         *   dialog or an activity.
          */
-        object Handled : OnTriggeredResult()
+        data class Handled(val actionLaunched: Boolean) : OnTriggeredResult()
 
         /**
          * Returning this as a result from the [onTriggered] method means that the implementation
          * has _not_ taken care of the action and the system should start an activity using the
          * given [Intent].
          */
-        data class StartActivity(
-            val intent: Intent,
-            val canShowWhileLocked: Boolean,
-        ) : OnTriggeredResult()
+        data class StartActivity(val intent: Intent, val canShowWhileLocked: Boolean) :
+            OnTriggeredResult()
 
         /**
          * Returning this as a result from the [onTriggered] method means that the implementation
          * has _not_ taken care of the action and the system should show a Dialog using the given
          * [AlertDialog] and [Expandable].
          */
-        data class ShowDialog(
-            val dialog: AlertDialog,
-            val expandable: Expandable?,
-        ) : OnTriggeredResult()
+        data class ShowDialog(val dialog: AlertDialog, val expandable: Expandable?) :
+            OnTriggeredResult()
     }
 
+    /**
+     * Models an [OnTriggeredResult] that did or did not launch a dialog or activity for a given
+     * config key.
+     */
+    data class LaunchingFromTriggeredResult(val launched: Boolean, val configKey: String)
+
     companion object {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index f08576a..c774987 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -24,8 +24,8 @@
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
@@ -51,6 +51,7 @@
     @ShadeDisplayAware private val context: Context,
     private val userFileManager: UserFileManager,
     private val userTracker: UserTracker,
+    private val communalSettingsInteractor: CommunalSettingsInteractor,
     broadcastDispatcher: BroadcastDispatcher,
 ) : KeyguardQuickAffordanceSelectionManager {
 
@@ -102,7 +103,7 @@
                     // common case anyway as restoration really only happens on initial device
                     // setup).
                     emit(Unit)
-                }
+                },
             ) { _, _ ->
             }
             .flatMapLatest {
@@ -128,7 +129,11 @@
 
     override fun getSelections(): Map<String, List<String>> {
         // If the custom shortcuts feature is not enabled, ignore prior selections and use defaults
-        if (!context.resources.getBoolean(R.bool.custom_lockscreen_shortcuts_enabled)) {
+        // TODO(b/383391342): remove isV2FlagEnabled check and just depend on the resource
+        if (
+            !(context.resources.getBoolean(R.bool.custom_lockscreen_shortcuts_enabled) ||
+                communalSettingsInteractor.isV2FlagEnabled())
+        ) {
             return defaults
         }
 
@@ -164,10 +169,7 @@
         return result
     }
 
-    override fun setSelections(
-        slotId: String,
-        affordanceIds: List<String>,
-    ) {
+    override fun setSelections(slotId: String, affordanceIds: List<String>) {
         val key = "$KEY_PREFIX_SLOT$slotId"
         val value = affordanceIds.joinToString(AFFORDANCE_DELIMITER)
         sharedPrefs.edit().putString(key, value).apply()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
index 1358634..1c9bc9f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
@@ -21,6 +21,7 @@
 import android.media.AudioManager
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.Observer
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.common.shared.model.ContentDescription
@@ -45,7 +46,6 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
-import com.android.app.tracing.coroutines.launchTraced as launch
 import kotlinx.coroutines.withContext
 
 @SysUISingleton
@@ -118,7 +118,7 @@
                 audioManager.ringerModeInternal = newRingerMode
             }
         }
-        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
     }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState =
@@ -140,11 +140,11 @@
                 .getSharedPreferences(
                     MUTE_QUICK_AFFORDANCE_PREFS_FILE_NAME,
                     Context.MODE_PRIVATE,
-                    userTracker.userId
+                    userTracker.userId,
                 )
                 .getInt(
                     LAST_NON_SILENT_RINGER_MODE_KEY,
-                    ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE
+                    ringerModeTracker.ringerModeInternal.value ?: DEFAULT_LAST_NON_SILENT_VALUE,
                 )
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
index eafa1ce..cb7702e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/QuickAccessWalletKeyguardQuickAffordanceConfig.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
@@ -72,21 +71,15 @@
                         override fun onWalletCardsRetrieved(response: GetWalletCardsResponse) {
                             val hasCards =
                                 getPaymentCards(response.walletCards)?.isNotEmpty() == true
-                            trySendWithFailureLogging(
-                                hasCards,
-                                TAG,
-                            )
+                            trySendWithFailureLogging(hasCards, TAG)
                         }
 
                         override fun onWalletCardRetrievalError(error: GetWalletCardsError) {
                             Log.e(
                                 TAG,
-                                "Wallet card retrieval error, message: \"${error?.message}\""
+                                "Wallet card retrieval error, message: \"${error?.message}\"",
                             )
-                            trySendWithFailureLogging(
-                                null,
-                                TAG,
-                            )
+                            trySendWithFailureLogging(null, TAG)
                         }
                     }
 
@@ -94,7 +87,7 @@
                     callback,
                     QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE,
                     QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE,
-                    QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE
+                    QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE,
                 )
 
                 withContext(backgroundDispatcher) {
@@ -107,7 +100,7 @@
                     walletController.unregisterWalletChangeObservers(
                         QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE,
                         QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE,
-                        QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE
+                        QuickAccessWalletController.WalletChangeEvent.DEFAULT_WALLET_APP_CHANGE,
                     )
                 }
             }
@@ -117,11 +110,7 @@
                     if (hasCards == null) {
                         KeyguardQuickAffordanceConfig.LockScreenState.Hidden
                     } else {
-                        state(
-                            isWalletAvailable(),
-                            hasCards,
-                            walletController.walletClient.tileIcon,
-                        )
+                        state(isWalletAvailable(), hasCards, walletController.walletClient.tileIcon)
                     }
                 flowOf(state)
             }
@@ -135,28 +124,28 @@
                     explanation =
                         context.getString(
                             R.string.wallet_quick_affordance_unavailable_install_the_app
-                        ),
+                        )
                 )
             queryCards().isEmpty() ->
                 KeyguardQuickAffordanceConfig.PickerScreenState.Disabled(
                     explanation =
                         context.getString(
                             R.string.wallet_quick_affordance_unavailable_configure_the_app
-                        ),
+                        )
                 )
             else -> KeyguardQuickAffordanceConfig.PickerScreenState.Default()
         }
     }
 
     override fun onTriggered(
-        expandable: Expandable?,
+        expandable: Expandable?
     ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
         walletController.startQuickAccessUiIntent(
             activityStarter,
             expandable?.activityTransitionController(),
             /* hasCard= */ true,
         )
-        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+        return KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(true)
     }
 
     private suspend fun queryCards(): List<WalletCard> {
@@ -199,10 +188,8 @@
                     Icon.Loaded(
                         drawable = tileIcon,
                         contentDescription =
-                            ContentDescription.Resource(
-                                res = R.string.accessibility_wallet_button,
-                            ),
-                    ),
+                            ContentDescription.Resource(res = R.string.accessibility_wallet_button),
+                    )
             )
         } else {
             KeyguardQuickAffordanceConfig.LockScreenState.Hidden
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index d18d6dc..f792935 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -19,7 +19,6 @@
 
 import android.util.Log
 import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
@@ -121,9 +120,6 @@
             keyguardInteractor.clockShouldBeCentered
         }
 
-    fun setClockSize(@KeyguardClockSwitch.ClockSize size: Int) =
-        setClockSize(ClockSize.fromLegacy(size))
-
     fun setClockSize(size: ClockSize) {
         SceneContainerFlag.assertInLegacyMode()
         keyguardClockRepository.setClockSize(size)
@@ -134,7 +130,7 @@
             return clock?.let { clock -> clock.config.id }
                 ?: run {
                     Log.e(TAG, "No clock is available")
-                    KeyguardClockSwitch.MISSING_CLOCK_ID
+                    "MISSING_CLOCK_ID"
                 }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 0d9474e..0193d7cb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
 import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
@@ -37,6 +36,7 @@
 import com.android.systemui.keyguard.shared.model.DozeTransitionModel
 import com.android.systemui.keyguard.shared.model.Edge
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
 import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
@@ -93,6 +93,8 @@
     private val fromGoneTransitionInteractor: Provider<FromGoneTransitionInteractor>,
     private val fromLockscreenTransitionInteractor: Provider<FromLockscreenTransitionInteractor>,
     private val fromOccludedTransitionInteractor: Provider<FromOccludedTransitionInteractor>,
+    private val fromAlternateBouncerTransitionInteractor:
+        Provider<FromAlternateBouncerTransitionInteractor>,
     @Application applicationScope: CoroutineScope,
 ) {
     // TODO(b/296118689): move to a repository
@@ -119,13 +121,11 @@
                 // We offset the placeholder bounds by the configured top margin to account for
                 // legacy placement behavior within notifications for splitshade.
                 emit(
-                    if (MigrateClocksToBlueprint.isEnabled) {
-                        if (useSplitShade) {
-                            bounds.copy(bottom = bounds.bottom - keyguardSplitShadeTopMargin)
-                        } else {
-                            bounds
-                        }
-                    } else bounds
+                    if (useSplitShade) {
+                        bounds.copy(bottom = bounds.bottom - keyguardSplitShadeTopMargin)
+                    } else {
+                        bounds
+                    }
                 )
             }
             .stateIn(
@@ -337,9 +337,6 @@
     /** The approximate location on the screen of the face unlock sensor, if one is available. */
     val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
 
-    @Deprecated("Use the relevant TransitionViewModel")
-    val keyguardAlpha: Flow<Float> = repository.keyguardAlpha
-
     /** Temporary shim for fading out content when the brightness slider is used */
     @Deprecated("SceneContainer uses NotificationStackAppearanceInteractor")
     val panelAlpha: StateFlow<Float> = repository.panelAlpha.asStateFlow()
@@ -480,10 +477,6 @@
         repository.setQuickSettingsVisible(isVisible)
     }
 
-    fun setAlpha(alpha: Float) {
-        repository.setKeyguardAlpha(alpha)
-    }
-
     fun setPanelAlpha(alpha: Float) {
         repository.setPanelAlpha(alpha)
     }
@@ -526,6 +519,8 @@
         when (keyguardTransitionInteractor.transitionState.value.to) {
             LOCKSCREEN -> fromLockscreenTransitionInteractor.get().dismissKeyguard()
             OCCLUDED -> fromOccludedTransitionInteractor.get().dismissFromOccluded()
+            ALTERNATE_BOUNCER ->
+                fromAlternateBouncerTransitionInteractor.get().dismissAlternateBouncer()
             else -> Log.v(TAG, "Keyguard was dismissed, no direct transition call needed")
         }
     }
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 ae55825..7d8badd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -28,8 +28,8 @@
 import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.animation.Expandable
+import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.dock.DockManager
@@ -62,6 +62,7 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
@@ -90,6 +91,7 @@
     private val devicePolicyManager: DevicePolicyManager,
     private val dockManager: DockManager,
     private val biometricSettingsRepository: BiometricSettingsRepository,
+    private val communalSettingsInteractor: CommunalSettingsInteractor,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     @ShadeDisplayAware private val appContext: Context,
     private val sceneInteractor: Lazy<SceneInteractor>,
@@ -101,6 +103,14 @@
     val launchingAffordance: StateFlow<Boolean> = repository.get().launchingAffordance.asStateFlow()
 
     /**
+     * Whether a [KeyguardQuickAffordanceConfig.OnTriggeredResult] indicated that the system
+     * launched an activity or showed a dialog.
+     */
+    private val _launchingFromTriggeredResult =
+        MutableStateFlow<KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult?>(null)
+    val launchingFromTriggeredResult = _launchingFromTriggeredResult.asStateFlow()
+
+    /**
      * Whether the UI should use the long press gesture to activate quick affordances.
      *
      * If `false`, the UI goes back to using single taps.
@@ -187,18 +197,45 @@
         metricsLogger.logOnShortcutTriggered(slotId, configKey)
 
         when (val result = config.onTriggered(expandable)) {
-            is KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity ->
+            is KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity -> {
+                setLaunchingFromTriggeredResult(
+                    KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult(
+                        launched = true,
+                        configKey,
+                    )
+                )
                 launchQuickAffordance(
                     intent = result.intent,
                     canShowWhileLocked = result.canShowWhileLocked,
                     expandable = expandable,
                 )
-            is KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled -> Unit
-            is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog ->
+            }
+            is KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled -> {
+                setLaunchingFromTriggeredResult(
+                    KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult(
+                        result.actionLaunched,
+                        configKey,
+                    )
+                )
+            }
+            is KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog -> {
+                setLaunchingFromTriggeredResult(
+                    KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult(
+                        launched = true,
+                        configKey,
+                    )
+                )
                 showDialog(result.dialog, result.expandable)
+            }
         }
     }
 
+    fun setLaunchingFromTriggeredResult(
+        launchingResult: KeyguardQuickAffordanceConfig.LaunchingFromTriggeredResult?
+    ) {
+        _launchingFromTriggeredResult.value = launchingResult
+    }
+
     /**
      * Selects an affordance with the given ID on the slot with the given ID.
      *
@@ -427,7 +464,10 @@
                 name = Contract.FlagsTable.FLAG_NAME_CUSTOM_LOCK_SCREEN_QUICK_AFFORDANCES_ENABLED,
                 value =
                     !isFeatureDisabledByDevicePolicy() &&
-                        appContext.resources.getBoolean(R.bool.custom_lockscreen_shortcuts_enabled),
+                        // TODO(b/383391342): remove isV2FlagEnabled check once trunkfood is reached
+                        (appContext.resources.getBoolean(
+                            R.bool.custom_lockscreen_shortcuts_enabled
+                        ) || communalSettingsInteractor.isV2FlagEnabled()),
             ),
             KeyguardPickerFlag(
                 name = Contract.FlagsTable.FLAG_NAME_CUSTOM_CLOCKS_ENABLED,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
index 274a1dd..a650300 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTouchHandlingInteractor.kt
@@ -22,6 +22,7 @@
 import android.content.IntentFilter
 import android.view.accessibility.AccessibilityManager
 import androidx.annotation.VisibleForTesting
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.internal.logging.UiEvent
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.broadcast.BroadcastDispatcher
@@ -29,7 +30,6 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.res.R
@@ -51,7 +51,6 @@
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** Business logic for use-cases related to top-level touch handling in the lock screen. */
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -121,9 +120,7 @@
     init {
         if (isFeatureEnabled()) {
             broadcastDispatcher
-                .broadcastFlow(
-                    IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
-                )
+                .broadcastFlow(IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
                 .onEach { hideMenu() }
                 .launchIn(scope)
         }
@@ -188,8 +185,7 @@
     }
 
     private fun isFeatureEnabled(): Boolean {
-        return featureFlags.isEnabled(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED) &&
-            context.resources.getBoolean(R.bool.long_press_keyguard_customize_lockscreen_enabled)
+        return context.resources.getBoolean(R.bool.long_press_keyguard_customize_lockscreen_enabled)
     }
 
     /** Updates application state to ask to show the menu. */
@@ -230,14 +226,11 @@
             .toLong()
     }
 
-    enum class LogEvents(
-        private val _id: Int,
-    ) : UiEventLogger.UiEventEnum {
+    enum class LogEvents(private val _id: Int) : UiEventLogger.UiEventEnum {
         @UiEvent(doc = "The lock screen was long-pressed and we showed the settings popup menu.")
         LOCK_SCREEN_LONG_PRESS_POPUP_SHOWN(1292),
         @UiEvent(doc = "The lock screen long-press popup menu was clicked.")
-        LOCK_SCREEN_LONG_PRESS_POPUP_CLICKED(1293),
-        ;
+        LOCK_SCREEN_LONG_PRESS_POPUP_CLICKED(1293);
 
         override fun getId() = _id
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
index 21b9e53..24929b6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/ToAodFoldTransitionInteractor.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
-import android.view.ViewGroup
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.shade.NotificationPanelViewController
 import com.android.systemui.shade.ShadeFoldAnimator
@@ -25,16 +24,12 @@
 @SysUISingleton
 class ToAodFoldTransitionInteractor
 @Inject
-constructor(
-    private val keyguardClockInteractor: KeyguardClockInteractor,
-) {
+constructor(private val keyguardClockInteractor: KeyguardClockInteractor) {
     private var parentAnimator: NotificationPanelViewController.ShadeFoldAnimatorImpl? = null
 
     // TODO(b/331770313): Migrate to PowerInteractor; Deprecate ShadeFoldAnimator again
     val foldAnimator =
         object : ShadeFoldAnimator {
-            override val view: ViewGroup?
-                get() = throw NotImplementedError("Deprecated. Do not call.")
 
             override fun prepareFoldToAodAnimation() {
                 parentAnimator?.prepareFoldToAodAnimation()
@@ -43,7 +38,7 @@
             override fun startFoldToAodAnimation(
                 startAction: Runnable,
                 endAction: Runnable,
-                cancelAction: Runnable
+                cancelAction: Runnable,
             ) {
                 parentAnimator?.let {
                     it.buildViewAnimator(startAction, endAction, cancelAction)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
index aa44b6d..382436c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/scenetransition/LockscreenSceneTransitionInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.domain.interactor.scenetransition
 
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.compose.animation.scene.ObservableTransitionState
 import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.CoreStartable
@@ -38,7 +39,6 @@
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /**
  * This class listens to scene framework scene transitions and manages keyguard transition framework
@@ -111,7 +111,10 @@
         if (currentTransitionId == null) return
         if (prevTransition !is ObservableTransitionState.Transition) return
 
-        if (idle.currentScene == prevTransition.toContent) {
+        if (
+            idle.currentScene == prevTransition.toContent ||
+                idle.currentOverlays.contains(prevTransition.toContent)
+        ) {
             finishCurrentTransition()
         } else {
             val targetState =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt
index b661297..5003a19 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/ClockSize.kt
@@ -18,37 +18,19 @@
 package com.android.systemui.keyguard.shared.model
 
 import android.util.Log
-import com.android.keyguard.KeyguardClockSwitch
 
-enum class ClockSize(
-    @KeyguardClockSwitch.ClockSize val legacyValue: Int,
-) {
-    SMALL(KeyguardClockSwitch.SMALL),
-    LARGE(KeyguardClockSwitch.LARGE);
-
-    companion object {
-        private val TAG = ClockSize::class.simpleName!!
-        fun fromLegacy(@KeyguardClockSwitch.ClockSize value: Int): ClockSize {
-            for (enumVal in enumValues<ClockSize>()) {
-                if (enumVal.legacyValue == value) {
-                    return enumVal
-                }
-            }
-
-            Log.e(TAG, "Unrecognized legacy clock size value: $value")
-            return LARGE
-        }
-    }
+enum class ClockSize {
+    SMALL,
+    LARGE,
 }
 
-enum class ClockSizeSetting(
-    val settingValue: Int,
-) {
+enum class ClockSizeSetting(val settingValue: Int) {
     DYNAMIC(1),
     SMALL(0);
 
     companion object {
         private val TAG = ClockSizeSetting::class.simpleName!!
+
         fun fromSettingValue(value: Int): ClockSizeSetting {
             for (enumVal in enumValues<ClockSizeSetting>()) {
                 if (enumVal.settingValue == value) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
index e7803c5..a4a5ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBottomAreaVibrations.kt
@@ -17,12 +17,23 @@
 package com.android.systemui.keyguard.ui.binder
 
 import android.os.VibrationEffect
+import com.android.systemui.Flags
 import kotlin.time.Duration.Companion.milliseconds
 
 object KeyguardBottomAreaVibrations {
 
-    val ShakeAnimationDuration = 300.milliseconds
-    const val ShakeAnimationCycles = 5f
+    val ShakeAnimationDuration =
+        if (Flags.msdlFeedback()) {
+            285.milliseconds
+        } else {
+            300.milliseconds
+        }
+    val ShakeAnimationCycles =
+        if (Flags.msdlFeedback()) {
+            3f
+        } else {
+            5f
+        }
 
     private const val SmallVibrationScale = 0.3f
     private const val BigVibrationScale = 0.6f
@@ -32,7 +43,7 @@
             .apply {
                 val vibrationDelayMs =
                     (ShakeAnimationDuration.inWholeMilliseconds / (ShakeAnimationCycles * 2))
-                    .toInt()
+                        .toInt()
 
                 val vibrationCount = ShakeAnimationCycles.toInt() * 2
                 repeat(vibrationCount) {
@@ -47,29 +58,13 @@
 
     val Activated =
         VibrationEffect.startComposition()
-            .addPrimitive(
-                VibrationEffect.Composition.PRIMITIVE_TICK,
-                BigVibrationScale,
-                0,
-            )
-            .addPrimitive(
-                VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
-                0.1f,
-                0,
-            )
+            .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, BigVibrationScale, 0)
+            .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.1f, 0)
             .compose()
 
     val Deactivated =
         VibrationEffect.startComposition()
-            .addPrimitive(
-                VibrationEffect.Composition.PRIMITIVE_TICK,
-                BigVibrationScale,
-                0,
-            )
-            .addPrimitive(
-                VibrationEffect.Composition.PRIMITIVE_QUICK_FALL,
-                0.1f,
-                0,
-            )
+            .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, BigVibrationScale, 0)
+            .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL, 0.1f, 0)
             .compose()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
index 1964cb2..d3b76a5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardPreviewClockViewBinder.kt
@@ -84,7 +84,7 @@
                             lastClock = currentClock
                             updateClockAppearance(
                                 currentClock,
-                                clockPreviewConfig.previewContext.resources,
+                                clockPreviewConfig.context.resources,
                             )
 
                             if (viewModel.shouldHighlightSelectedAffordance) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
index 8725cdd..8a2e3dd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardQuickAffordanceViewBinder.kt
@@ -20,6 +20,7 @@
 import android.annotation.SuppressLint
 import android.content.res.ColorStateList
 import android.graphics.drawable.Animatable2
+import android.os.VibrationEffect
 import android.util.Size
 import android.view.View
 import android.view.ViewGroup
@@ -33,25 +34,27 @@
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
+import com.android.systemui.Flags
 import com.android.systemui.animation.Expandable
 import com.android.systemui.animation.view.LaunchableImageView
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.ui.binder.IconViewBinder
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceHapticViewModel
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.util.doOnEnd
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.MSDLPlayer
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** This is only for a SINGLE Quick affordance */
 @SysUISingleton
@@ -60,8 +63,9 @@
 constructor(
     private val falsingManager: FalsingManager?,
     private val vibratorHelper: VibratorHelper?,
+    private val msdlPlayer: MSDLPlayer,
     private val logger: KeyguardQuickAffordancesLogger,
-    @Main private val mainImmediateDispatcher: CoroutineDispatcher,
+    private val hapticsViewModelFactory: KeyguardQuickAffordanceHapticViewModel.Factory,
 ) {
 
     private val EXIT_DOZE_BUTTON_REVEAL_ANIMATION_DURATION_MS = 250L
@@ -88,6 +92,12 @@
     ): Binding {
         val button = view as ImageView
         val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
+        val hapticsViewModel =
+            if (Flags.msdlFeedback()) {
+                hapticsViewModelFactory.create(viewModel)
+            } else {
+                null
+            }
         val disposableHandle =
             view.repeatWhenAttached {
                 repeatOnLifecycle(Lifecycle.State.STARTED) {
@@ -98,15 +108,12 @@
                                 viewModel = buttonModel,
                                 messageDisplayer = messageDisplayer,
                             )
+                            hapticsViewModel?.updateActivatedHistory(buttonModel.isActivated)
                         }
                     }
 
                     launch {
-                        updateButtonAlpha(
-                            view = button,
-                            viewModel = viewModel,
-                            alphaFlow = alpha,
-                        )
+                        updateButtonAlpha(view = button, viewModel = viewModel, alphaFlow = alpha)
                     }
 
                     launch {
@@ -117,6 +124,32 @@
                             }
                         }
                     }
+
+                    if (Flags.msdlFeedback()) {
+                        launch {
+                            hapticsViewModel
+                                ?.quickAffordanceHapticState
+                                ?.filter {
+                                    it !=
+                                        KeyguardQuickAffordanceHapticViewModel.HapticState
+                                            .NO_HAPTICS
+                                }
+                                ?.collect { state ->
+                                    when (state) {
+                                        KeyguardQuickAffordanceHapticViewModel.HapticState
+                                            .TOGGLE_ON -> msdlPlayer.playToken(MSDLToken.SWITCH_ON)
+                                        KeyguardQuickAffordanceHapticViewModel.HapticState
+                                            .TOGGLE_OFF ->
+                                            msdlPlayer.playToken(MSDLToken.SWITCH_OFF)
+                                        KeyguardQuickAffordanceHapticViewModel.HapticState.LAUNCH ->
+                                            msdlPlayer.playToken(MSDLToken.LONG_PRESS)
+                                        KeyguardQuickAffordanceHapticViewModel.HapticState
+                                            .NO_HAPTICS -> Unit
+                                    }
+                                    hapticsViewModel.resetLaunchingFromTriggeredResult()
+                                }
+                        }
+                    }
                 }
             }
 
@@ -178,7 +211,7 @@
                     com.android.internal.R.color.materialColorOnPrimaryFixed
                 } else {
                     com.android.internal.R.color.materialColorOnSurface
-                },
+                }
             )
         )
 
@@ -221,12 +254,7 @@
                             .getDimensionPixelSize(R.dimen.keyguard_affordance_shake_amplitude)
                             .toFloat()
                     val shakeAnimator =
-                        ObjectAnimator.ofFloat(
-                            view,
-                            "translationX",
-                            -amplitude / 2,
-                            amplitude / 2,
-                        )
+                        ObjectAnimator.ofFloat(view, "translationX", -amplitude / 2, amplitude / 2)
                     shakeAnimator.duration =
                         KeyguardBottomAreaVibrations.ShakeAnimationDuration.inWholeMilliseconds
                     shakeAnimator.interpolator =
@@ -234,11 +262,17 @@
                     shakeAnimator.doOnEnd { view.translationX = 0f }
                     shakeAnimator.start()
 
-                    vibratorHelper?.vibrate(KeyguardBottomAreaVibrations.Shake)
+                    vibratorHelper?.playFeedback(KeyguardBottomAreaVibrations.Shake, msdlPlayer)
                     logger.logQuickAffordanceTapped(viewModel.configKey)
                 }
                 view.onLongClickListener =
-                    OnLongClickListener(falsingManager, viewModel, vibratorHelper, onTouchListener)
+                    OnLongClickListener(
+                        falsingManager,
+                        viewModel,
+                        vibratorHelper,
+                        onTouchListener,
+                        msdlPlayer,
+                    )
             } else {
                 view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
             }
@@ -268,7 +302,7 @@
                 Size(
                     view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
                     view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height),
-                ),
+                )
         )
     }
 
@@ -297,7 +331,8 @@
         private val falsingManager: FalsingManager?,
         private val viewModel: KeyguardQuickAffordanceViewModel,
         private val vibratorHelper: VibratorHelper?,
-        private val onTouchListener: KeyguardQuickAffordanceOnTouchListener
+        private val onTouchListener: KeyguardQuickAffordanceOnTouchListener,
+        private val msdlPlayer: MSDLPlayer,
     ) : View.OnLongClickListener {
         override fun onLongClick(view: View): Boolean {
             if (falsingManager?.isFalseLongTap(FalsingManager.MODERATE_PENALTY) == true) {
@@ -312,12 +347,13 @@
                         slotId = viewModel.slotId,
                     )
                 )
-                vibratorHelper?.vibrate(
+                vibratorHelper?.playFeedback(
                     if (viewModel.isActivated) {
                         KeyguardBottomAreaVibrations.Activated
                     } else {
                         KeyguardBottomAreaVibrations.Deactivated
-                    }
+                    },
+                    msdlPlayer,
                 )
             }
 
@@ -328,7 +364,15 @@
         override fun onLongClickUseDefaultHapticFeedback(view: View) = false
     }
 
-    private data class ConfigurationBasedDimensions(
-        val buttonSizePx: Size,
-    )
+    private data class ConfigurationBasedDimensions(val buttonSizePx: Size)
+}
+
+private fun VibratorHelper.playFeedback(effect: VibrationEffect, msdlPlayer: MSDLPlayer) {
+    if (!Flags.msdlFeedback()) {
+        vibrate(effect)
+    } else {
+        if (effect == KeyguardBottomAreaVibrations.Shake) {
+            msdlPlayer.playToken(MSDLToken.FAILURE)
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index a2ce4ec..6d270b2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -127,21 +127,18 @@
                     if (Flags.nonTouchscreenDevicesBypassFalsing()) {
                         if (
                             event.action == MotionEvent.ACTION_DOWN &&
-                            event.buttonState == MotionEvent.BUTTON_PRIMARY &&
-                            !event.isTouchscreenSource()
+                                event.buttonState == MotionEvent.BUTTON_PRIMARY &&
+                                !event.isTouchscreenSource()
                         ) {
                             consumed = true
                         } else if (
-                            event.action == MotionEvent.ACTION_UP &&
-                            !event.isTouchscreenSource()
+                            event.action == MotionEvent.ACTION_UP && !event.isTouchscreenSource()
                         ) {
                             statusBarKeyguardViewManager?.showBouncer(true)
                             consumed = true
                         }
                     }
-                    viewModel.setRootViewLastTapPosition(
-                        Point(event.x.toInt(), event.y.toInt())
-                    )
+                    viewModel.setRootViewLastTapPosition(Point(event.x.toInt(), event.y.toInt()))
                 }
                 consumed
             }
@@ -172,7 +169,6 @@
                     launch("$TAG#alpha") {
                         viewModel.alpha(viewState).collect { alpha ->
                             view.alpha = alpha
-                            childViews[statusViewId]?.alpha = alpha
                             childViews[burnInLayerId]?.alpha = alpha
                         }
                     }
@@ -253,18 +249,6 @@
                     }
 
                     launch {
-                        viewModel.burnInLayerAlpha.collect { alpha ->
-                            childViews[statusViewId]?.alpha = alpha
-                        }
-                    }
-
-                    launch {
-                        viewModel.lockscreenStateAlpha(viewState).collect { alpha ->
-                            childViews[statusViewId]?.alpha = alpha
-                        }
-                    }
-
-                    launch {
                         viewModel.scale.collect { scaleViewModel ->
                             if (scaleViewModel.scaleClockOnly) {
                                 // For clocks except weather clock, we have scale transition besides
@@ -553,7 +537,6 @@
         return device?.supportsSource(InputDevice.SOURCE_TOUCHSCREEN) == true
     }
 
-    private val statusViewId = R.id.keyguard_status_view
     private val burnInLayerId = R.id.burn_in_layer
     private val aodNotificationIconContainerId = R.id.aod_notification_icon_container
     private val largeClockId = customR.id.lockscreen_clock_view_large
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
index 79360370..13c2ffb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardSettingsViewBinder.kt
@@ -19,6 +19,8 @@
 
 import android.graphics.Rect
 import android.view.View
+import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED
+import android.widget.TextView
 import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
@@ -47,7 +49,7 @@
         touchHandlingViewModel: KeyguardTouchHandlingViewModel,
         rootViewModel: KeyguardRootViewModel?,
         vibratorHelper: VibratorHelper,
-        activityStarter: ActivityStarter
+        activityStarter: ActivityStarter,
     ): DisposableHandle {
         val disposableHandle =
             view.repeatWhenAttached {
@@ -57,19 +59,16 @@
                             view.animateVisibility(visible = isVisible)
                             if (isVisible) {
                                 vibratorHelper.vibrate(KeyguardBottomAreaVibrations.Activated)
+                                val textView = view.requireViewById(R.id.text) as TextView
                                 view.setOnTouchListener(
-                                    KeyguardSettingsButtonOnTouchListener(
-                                        viewModel = viewModel,
-                                    )
+                                    KeyguardSettingsButtonOnTouchListener(viewModel = viewModel)
                                 )
                                 IconViewBinder.bind(
                                     icon = viewModel.icon,
                                     view = view.requireViewById(R.id.icon),
                                 )
-                                TextViewBinder.bind(
-                                    view = view.requireViewById(R.id.text),
-                                    viewModel = viewModel.text,
-                                )
+                                TextViewBinder.bind(view = textView, viewModel = viewModel.text)
+                                textView.sendAccessibilityEvent(TYPE_VIEW_FOCUSED)
                             }
                         }
                     }
@@ -108,15 +107,12 @@
     }
 
     /** Opens the wallpaper picker screen after the device is unlocked by the user. */
-    private fun navigateToLockScreenSettings(
-        activityStarter: ActivityStarter,
-        view: View,
-    ) {
+    private fun navigateToLockScreenSettings(activityStarter: ActivityStarter, view: View) {
         activityStarter.postStartActivityDismissingKeyguard(
             WallpaperPickerIntentUtils.getIntent(view.context, LAUNCH_SOURCE_KEYGUARD),
             /* delay= */ 0,
             /* animationController= */ ActivityTransitionAnimator.Controller.fromView(view),
-            /* customMessage= */ view.context.getString(R.string.keyguard_unlock_to_customize_ls)
+            /* customMessage= */ view.context.getString(R.string.keyguard_unlock_to_customize_ls),
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index 090b659..6fb31c0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -48,19 +48,16 @@
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import androidx.core.view.isInvisible
-import com.android.internal.policy.SystemBarUtils
 import com.android.keyguard.ClockEventController
-import com.android.keyguard.KeyguardClockSwitch
 import com.android.systemui.animation.view.LaunchableImageView
 import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.communal.ui.binder.CommunalTutorialIndicatorViewBinder
 import com.android.systemui.communal.ui.viewmodel.CommunalTutorialIndicatorViewModel
-import com.android.systemui.coroutines.newTracingContext
+import com.android.systemui.customization.R as customR
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
@@ -80,7 +77,6 @@
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shared.clocks.ClockRegistry
-import com.android.systemui.shared.clocks.DefaultClockController
 import com.android.systemui.shared.clocks.shared.model.ClockPreviewConstants
 import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
 import com.android.systemui.shared.quickaffordance.shared.model.KeyguardPreviewConstants
@@ -91,18 +87,13 @@
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedInject
 import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.cancel
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
 import org.json.JSONException
 import org.json.JSONObject
-import com.android.app.tracing.coroutines.launchTraced as launch
-import com.android.systemui.customization.R as customR
 
 /** Renders the preview of the lock screen. */
 class KeyguardPreviewRenderer
@@ -110,7 +101,6 @@
 @AssistedInject
 constructor(
     @Application private val context: Context,
-    @Application applicationScope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
     @Main private val mainHandler: Handler,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
@@ -157,8 +147,6 @@
     val surfacePackage: SurfaceControlViewHost.SurfacePackage
         get() = checkNotNull(host.surfacePackage)
 
-    private lateinit var largeClockHostView: FrameLayout
-    private lateinit var smallClockHostView: FrameLayout
     private var smartSpaceView: View? = null
 
     private val disposables = DisposableHandles()
@@ -166,29 +154,18 @@
 
     private val shortcutsBindings = mutableSetOf<KeyguardQuickAffordanceViewBinder.Binding>()
 
-    private val coroutineScope: CoroutineScope
-
     @Style.Type private var themeStyle: Int? = null
 
     init {
-        coroutineScope =
-            CoroutineScope(
-                applicationScope.coroutineContext +
-                    Job() +
-                    newTracingContext("KeyguardPreviewRenderer")
-            )
-        disposables += DisposableHandle { coroutineScope.cancel() }
         clockController.setFallbackWeatherData(WeatherData.getPlaceholderWeatherData())
-
         quickAffordancesCombinedViewModel.enablePreviewMode(
             initiallySelectedSlotId =
-            bundle.getString(KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID)
-                ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+                bundle.getString(KeyguardPreviewConstants.KEY_INITIALLY_SELECTED_SLOT_ID)
+                    ?: KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
             shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance,
         )
-        if (MigrateClocksToBlueprint.isEnabled) {
-            clockViewModel.shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance
-        }
+
+        clockViewModel.shouldHighlightSelectedAffordance = shouldHighlightSelectedAffordance
         runBlocking(mainDispatcher) {
             host =
                 SurfaceControlViewHost(
@@ -348,6 +325,7 @@
         smartSpaceView?.alpha = if (shouldHighlightSelectedAffordance) DIM_ALPHA else 1.0f
     }
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     private fun setupKeyguardRootView(previewContext: Context, rootView: FrameLayout) {
         val keyguardRootView = KeyguardRootView(previewContext, null)
         rootView.addView(
@@ -358,34 +336,23 @@
             ),
         )
 
-        setUpUdfps(
-            previewContext,
-            if (MigrateClocksToBlueprint.isEnabled) keyguardRootView else rootView,
-        )
+        setUpUdfps(previewContext, keyguardRootView)
 
         setupShortcuts(keyguardRootView)
 
         if (!shouldHideClock) {
             setUpClock(previewContext, rootView)
-            if (MigrateClocksToBlueprint.isEnabled) {
-                KeyguardPreviewClockViewBinder.bind(
-                    keyguardRootView,
-                    clockViewModel,
-                    clockRegistry,
-                    ::updateClockAppearance,
-                    ClockPreviewConfig(
-                        previewContext,
-                        getPreviewShadeLayoutWide(display!!),
-                        SceneContainerFlag.isEnabled,
-                    ),
-                )
-            } else {
-                KeyguardPreviewClockViewBinder.bind(
-                    largeClockHostView,
-                    smallClockHostView,
-                    clockViewModel,
-                )
-            }
+            KeyguardPreviewClockViewBinder.bind(
+                keyguardRootView,
+                clockViewModel,
+                clockRegistry,
+                ::updateClockAppearance,
+                ClockPreviewConfig(
+                    previewContext,
+                    getPreviewShadeLayoutWide(display!!),
+                    SceneContainerFlag.isEnabled,
+                ),
+            )
         }
 
         setUpSmartspace(previewContext, rootView)
@@ -451,82 +418,22 @@
                 .inflate(R.layout.udfps_keyguard_preview, parentView, false) as View
 
         // Place the UDFPS view in the proper sensor location
-        if (MigrateClocksToBlueprint.isEnabled) {
-            val lockId = KeyguardPreviewClockViewBinder.lockId
-            finger.id = lockId
-            parentView.addView(finger)
-            val cs = ConstraintSet()
-            cs.clone(parentView as ConstraintLayout)
-            cs.apply {
-                constrainWidth(lockId, sensorBounds.width())
-                constrainHeight(lockId, sensorBounds.height())
-                connect(lockId, TOP, PARENT_ID, TOP, sensorBounds.top)
-                connect(lockId, START, PARENT_ID, START, sensorBounds.left)
-            }
-            cs.applyTo(parentView)
-        } else {
-            val fingerprintLayoutParams =
-                FrameLayout.LayoutParams(sensorBounds.width(), sensorBounds.height())
-            fingerprintLayoutParams.setMarginsRelative(
-                sensorBounds.left,
-                sensorBounds.top,
-                sensorBounds.right,
-                sensorBounds.bottom,
-            )
-            parentView.addView(finger, fingerprintLayoutParams)
+        val lockId = KeyguardPreviewClockViewBinder.lockId
+        finger.id = lockId
+        parentView.addView(finger)
+        val cs = ConstraintSet()
+        cs.clone(parentView as ConstraintLayout)
+        cs.apply {
+            constrainWidth(lockId, sensorBounds.width())
+            constrainHeight(lockId, sensorBounds.height())
+            connect(lockId, TOP, PARENT_ID, TOP, sensorBounds.top)
+            connect(lockId, START, PARENT_ID, START, sensorBounds.left)
         }
+        cs.applyTo(parentView)
     }
 
     private fun setUpClock(previewContext: Context, parentView: ViewGroup) {
         val resources = parentView.resources
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            largeClockHostView = FrameLayout(previewContext)
-            largeClockHostView.layoutParams =
-                FrameLayout.LayoutParams(
-                    FrameLayout.LayoutParams.MATCH_PARENT,
-                    FrameLayout.LayoutParams.MATCH_PARENT,
-                )
-            largeClockHostView.isInvisible = true
-            parentView.addView(largeClockHostView)
-
-            smallClockHostView = FrameLayout(previewContext)
-            val layoutParams =
-                FrameLayout.LayoutParams(
-                    FrameLayout.LayoutParams.WRAP_CONTENT,
-                    resources.getDimensionPixelSize(customR.dimen.small_clock_height),
-                )
-            layoutParams.topMargin =
-                SystemBarUtils.getStatusBarHeight(previewContext) +
-                    resources.getDimensionPixelSize(customR.dimen.small_clock_padding_top)
-            smallClockHostView.layoutParams = layoutParams
-            smallClockHostView.setPaddingRelative(
-                /* start = */ resources.getDimensionPixelSize(customR.dimen.clock_padding_start),
-                /* top = */ 0,
-                /* end = */ 0,
-                /* bottom = */ 0,
-            )
-            smallClockHostView.clipChildren = false
-            parentView.addView(smallClockHostView)
-            smallClockHostView.isInvisible = true
-        }
-
-        // TODO (b/283465254): Move the listeners to KeyguardClockRepository
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            val clockChangeListener =
-                object : ClockRegistry.ClockChangeListener {
-                    override fun onCurrentClockChanged() {
-                        onClockChanged()
-                    }
-                }
-            clockRegistry.registerClockChangeListener(clockChangeListener)
-            disposables += DisposableHandle {
-                clockRegistry.unregisterClockChangeListener(clockChangeListener)
-            }
-
-            clockController.registerListeners(parentView)
-            disposables += DisposableHandle { clockController.unregisterListeners() }
-        }
-
         val receiver =
             object : BroadcastReceiver() {
                 override fun onReceive(context: Context?, intent: Intent?) {
@@ -544,38 +451,9 @@
             },
         )
         disposables += DisposableHandle { broadcastDispatcher.unregisterReceiver(receiver) }
-
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            val layoutChangeListener =
-                View.OnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
-                    if (clockController.clock !is DefaultClockController) {
-                        clockController.clock
-                            ?.largeClock
-                            ?.events
-                            ?.onTargetRegionChanged(
-                                KeyguardClockSwitch.getLargeClockRegion(parentView)
-                            )
-                        clockController.clock
-                            ?.smallClock
-                            ?.events
-                            ?.onTargetRegionChanged(
-                                KeyguardClockSwitch.getSmallClockRegion(parentView)
-                            )
-                    }
-                }
-            parentView.addOnLayoutChangeListener(layoutChangeListener)
-            disposables += DisposableHandle {
-                parentView.removeOnLayoutChangeListener(layoutChangeListener)
-            }
-        }
-
-        onClockChanged()
     }
 
     private suspend fun updateClockAppearance(clock: ClockController, resources: Resources) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            clockController.clock = clock
-        }
         val colors = wallpaperColors
         if (clockRegistry.seedColor == null && colors != null) {
             // Seed color null means users do not override any color on the clock. The default
@@ -601,9 +479,7 @@
         // In clock preview, we should have a seed color for clock
         // before setting clock to clockEventController to avoid updateColor with seedColor == null
         // So in update colors, it should already have the correct theme in clockFaceController
-        if (MigrateClocksToBlueprint.isEnabled) {
-            clockController.clock = clock
-        }
+        clockController.clock = clock
         // When set clock to clockController,it will reset fontsize based on context.resources
         // We need to override it with overlaid resources
         clock.largeClock.events.onFontSettingChanged(
@@ -611,19 +487,6 @@
         )
     }
 
-    private fun onClockChanged() {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        coroutineScope.launch {
-            val clock = clockRegistry.createCurrentClock()
-            clockController.clock = clock
-            updateClockAppearance(clock, context.resources)
-            updateLargeClock(clock)
-            updateSmallClock(clock)
-        }
-    }
-
     private fun setupCommunalTutorialIndicator(keyguardRootView: ConstraintLayout) {
         keyguardRootView.findViewById<TextView>(R.id.communal_tutorial_indicator)?.let {
             indicatorView ->
@@ -657,34 +520,6 @@
         }
     }
 
-    private fun updateLargeClock(clock: ClockController) {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        clock.largeClock.events.onTargetRegionChanged(
-            KeyguardClockSwitch.getLargeClockRegion(largeClockHostView)
-        )
-        if (shouldHighlightSelectedAffordance) {
-            clock.largeClock.view.alpha = DIM_ALPHA
-        }
-        largeClockHostView.removeAllViews()
-        largeClockHostView.addView(clock.largeClock.view)
-    }
-
-    private fun updateSmallClock(clock: ClockController) {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        clock.smallClock.events.onTargetRegionChanged(
-            KeyguardClockSwitch.getSmallClockRegion(smallClockHostView)
-        )
-        if (shouldHighlightSelectedAffordance) {
-            clock.smallClock.view.alpha = DIM_ALPHA
-        }
-        smallClockHostView.removeAllViews()
-        smallClockHostView.addView(clock.smallClock.view)
-    }
-
     private fun getPreviewShadeLayoutWide(display: Display): Boolean {
         return if (display.displayId == 0) {
             shadeInteractor.isShadeLayoutWide.value
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt
index cafc909..16cb450 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt
@@ -16,6 +16,10 @@
 
 package com.android.systemui.keyguard.ui.transitions
 
+import android.content.res.Resources
+import com.android.systemui.Flags.notificationShadeBlur
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.DozingToPrimaryBouncerTransitionViewModel
@@ -25,9 +29,12 @@
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGlanceableHubTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel
+import com.android.systemui.res.R
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.IntoSet
+import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 
@@ -40,11 +47,6 @@
 interface PrimaryBouncerTransition {
     /** Radius of blur applied to the window's root view. */
     val windowBlurRadius: Flow<Float>
-
-    companion object {
-        const val MAX_BACKGROUND_BLUR_RADIUS = 150f
-        const val MIN_BACKGROUND_BLUR_RADIUS = 0f
-    }
 }
 
 /**
@@ -95,4 +97,26 @@
     @Binds
     @IntoSet
     fun toGone(impl: PrimaryBouncerToGoneTransitionViewModel): PrimaryBouncerTransition
+
+    companion object {
+        @Provides
+        @SysUISingleton
+        fun provideBlurConfig(@Main resources: Resources): BlurConfig {
+            val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius)
+            val maxBlurRadius =
+                if (notificationShadeBlur()) {
+                    resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius)
+                } else {
+                    resources.getDimensionPixelSize(R.dimen.max_window_blur_radius)
+                }
+            return BlurConfig(minBlurRadius.toFloat(), maxBlurRadius.toFloat())
+        }
+    }
+}
+
+/** Config that provides the max and min blur radius for the window blurs. */
+data class BlurConfig(val minBlurRadiusPx: Float, val maxBlurRadiusPx: Float) {
+    // No-op config that will be used by dagger of other SysUI variants which don't blur the
+    // background surface.
+    @Inject constructor() : this(0.0f, 0.0f)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
index d5a9655..6973fec 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt
@@ -31,7 +31,6 @@
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
-import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultUdfpsAccessibilityOverlaySection
 import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule.Companion.KEYGUARD_AMBIENT_INDICATION_AREA_SECTION
 import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSliceViewSection
@@ -60,7 +59,6 @@
     @Named(KEYGUARD_AMBIENT_INDICATION_AREA_SECTION)
     defaultAmbientIndicationAreaSection: Optional<KeyguardSection>,
     defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
-    defaultStatusViewSection: DefaultStatusViewSection,
     defaultStatusBarSection: DefaultStatusBarSection,
     defaultNotificationStackScrollLayoutSection: DefaultNotificationStackScrollLayoutSection,
     aodNotificationIconsSection: AodNotificationIconsSection,
@@ -80,7 +78,6 @@
             defaultShortcutsSection,
             defaultAmbientIndicationAreaSection.getOrNull(),
             defaultSettingsPopupMenuSection,
-            defaultStatusViewSection,
             defaultStatusBarSection,
             defaultNotificationStackScrollLayoutSection,
             aodNotificationIconsSection,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
index 3447177..1eed224 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/SplitShadeKeyguardBlueprint.kt
@@ -30,7 +30,6 @@
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultSettingsPopupMenuSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultShortcutsSection
 import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusBarSection
-import com.android.systemui.keyguard.ui.view.layout.sections.DefaultStatusViewSection
 import com.android.systemui.keyguard.ui.view.layout.sections.KeyguardSectionsModule
 import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
 import com.android.systemui.keyguard.ui.view.layout.sections.SplitShadeGuidelines
@@ -57,7 +56,6 @@
     @Named(KeyguardSectionsModule.KEYGUARD_AMBIENT_INDICATION_AREA_SECTION)
     defaultAmbientIndicationAreaSection: Optional<KeyguardSection>,
     defaultSettingsPopupMenuSection: DefaultSettingsPopupMenuSection,
-    defaultStatusViewSection: DefaultStatusViewSection,
     defaultStatusBarSection: DefaultStatusBarSection,
     splitShadeNotificationStackScrollLayoutSection: SplitShadeNotificationStackScrollLayoutSection,
     splitShadeGuidelines: SplitShadeGuidelines,
@@ -77,7 +75,6 @@
             defaultShortcutsSection,
             defaultAmbientIndicationAreaSection.getOrNull(),
             defaultSettingsPopupMenuSection,
-            defaultStatusViewSection,
             defaultStatusBarSection,
             splitShadeNotificationStackScrollLayoutSection,
             splitShadeGuidelines,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
index 160380b..57fe15d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodBurnInSection.kt
@@ -24,7 +24,6 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.keyguard.ui.view.KeyguardRootView
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
@@ -50,9 +49,6 @@
     }
 
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         if (emptyView.parent != null) {
             // As emptyView is lazy, it might be already attached.
             (emptyView.parent as? ViewGroup)?.removeView(emptyView)
@@ -68,17 +64,10 @@
     }
 
     override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         clockViewModel.burnInLayer = burnInLayer
     }
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         constraintSet.apply {
             // The empty view should not occupy any space
             constrainHeight(R.id.burn_in_layer_empty_view, 1)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index 70bf8bc..738fb73 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -32,7 +32,6 @@
 import androidx.constraintlayout.widget.ConstraintSet.WRAP_CONTENT
 import com.android.systemui.customization.R as customR
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardSection
@@ -82,9 +81,6 @@
     override fun addViews(constraintLayout: ConstraintLayout) {}
 
     override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         disposableHandle?.dispose()
         disposableHandle =
             KeyguardClockViewBinder.bind(
@@ -99,20 +95,12 @@
     }
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         keyguardClockViewModel.currentClock.value?.let { clock ->
             constraintSet.applyDeltaFrom(buildConstraints(clock, constraintSet))
         }
     }
 
     override fun removeViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         disposableHandle?.dispose()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
index 3a791fd..4bfe5f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt
@@ -24,7 +24,6 @@
 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.res.R
 import com.android.systemui.shade.LargeScreenHeaderHelper
 import com.android.systemui.shade.NotificationPanelView
@@ -54,32 +53,25 @@
         sharedNotificationContainerBinder,
     ) {
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         constraintSet.apply {
             val bottomMargin =
                 context.resources.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin)
-            if (MigrateClocksToBlueprint.isEnabled) {
-                val useLargeScreenHeader =
-                    context.resources.getBoolean(R.bool.config_use_large_screen_shade_header)
-                val marginTopLargeScreen =
-                    largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
-                connect(
-                    R.id.nssl_placeholder,
-                    TOP,
-                    R.id.smart_space_barrier_bottom,
-                    BOTTOM,
-                    bottomMargin +
-                        if (useLargeScreenHeader) {
-                            marginTopLargeScreen
-                        } else {
-                            0
-                        }
-                )
-            } else {
-                connect(R.id.nssl_placeholder, TOP, R.id.keyguard_status_view, BOTTOM, bottomMargin)
-            }
+            val useLargeScreenHeader =
+                context.resources.getBoolean(R.bool.config_use_large_screen_shade_header)
+            val marginTopLargeScreen =
+                largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+            connect(
+                R.id.nssl_placeholder,
+                TOP,
+                R.id.smart_space_barrier_bottom,
+                BOTTOM,
+                bottomMargin +
+                    if (useLargeScreenHeader) {
+                        marginTopLargeScreen
+                    } else {
+                        0
+                    },
+            )
             connect(R.id.nssl_placeholder, START, PARENT_ID, START)
             connect(R.id.nssl_placeholder, END, PARENT_ID, END)
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
deleted file mode 100644
index 57ea1ad..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package com.android.systemui.keyguard.ui.view.layout.sections
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.constraintlayout.widget.ConstraintSet.END
-import androidx.constraintlayout.widget.ConstraintSet.MATCH_CONSTRAINT
-import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
-import androidx.constraintlayout.widget.ConstraintSet.START
-import androidx.constraintlayout.widget.ConstraintSet.TOP
-import com.android.keyguard.KeyguardStatusView
-import com.android.keyguard.dagger.KeyguardStatusViewComponent
-import com.android.systemui.keyguard.KeyguardViewConfigurator
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.media.controls.ui.controller.KeyguardMediaController
-import com.android.systemui.res.R
-import com.android.systemui.shade.NotificationPanelView
-import com.android.systemui.shade.NotificationPanelViewController
-import com.android.systemui.shade.ShadeDisplayAware
-import com.android.systemui.statusbar.policy.SplitShadeStateController
-import com.android.systemui.util.Utils
-import dagger.Lazy
-import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-
-class DefaultStatusViewSection
-@Inject
-constructor(
-    @ShadeDisplayAware private val context: Context,
-    private val notificationPanelView: NotificationPanelView,
-    private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
-    private val keyguardViewConfigurator: Lazy<KeyguardViewConfigurator>,
-    private val notificationPanelViewController: Lazy<NotificationPanelViewController>,
-    private val keyguardMediaController: KeyguardMediaController,
-    private val splitShadeStateController: SplitShadeStateController,
-) : KeyguardSection() {
-    private val statusViewId = R.id.keyguard_status_view
-
-    override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        // At startup, 2 views with the ID `R.id.keyguard_status_view` will be available.
-        // Disable one of them
-        notificationPanelView.findViewById<View>(statusViewId)?.let {
-            notificationPanelView.removeView(it)
-        }
-        val keyguardStatusView =
-            (LayoutInflater.from(context)
-                    .inflate(R.layout.keyguard_status_view, constraintLayout, false)
-                    as KeyguardStatusView)
-                .apply { clipChildren = false }
-
-        // This is diassembled and moved to [AodNotificationIconsSection]
-        keyguardStatusView.findViewById<View>(R.id.left_aligned_notification_icon_container)?.let {
-            it.setVisibility(View.GONE)
-        }
-        // Should keep this even if flag, migrating clocks to blueprint, is on
-        // cause some events in clockEventController rely on keyguardStatusViewController
-        // TODO(b/313499340): clean up
-        constraintLayout.addView(keyguardStatusView)
-    }
-
-    override fun bindData(constraintLayout: ConstraintLayout) {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            constraintLayout.findViewById<KeyguardStatusView?>(R.id.keyguard_status_view)?.let {
-                val statusViewComponent =
-                    keyguardStatusViewComponentFactory.build(it, context.display)
-                val controller = statusViewComponent.keyguardStatusViewController
-                controller.init()
-                keyguardMediaController.attachSplitShadeContainer(
-                    it.requireViewById<ViewGroup>(R.id.status_view_media_container)
-                )
-                keyguardViewConfigurator.get().keyguardStatusViewController = controller
-                notificationPanelViewController.get().updateStatusViewController()
-            }
-        }
-    }
-
-    override fun applyConstraints(constraintSet: ConstraintSet) {
-        constraintSet.apply {
-            constrainWidth(statusViewId, MATCH_CONSTRAINT)
-            constrainHeight(statusViewId, WRAP_CONTENT)
-            // TODO(b/296122465): Constrain to the top of [DefaultStatusBarSection] and remove the
-            // extra margin below.
-            connect(statusViewId, TOP, PARENT_ID, TOP)
-            connect(statusViewId, START, PARENT_ID, START)
-            connect(statusViewId, END, PARENT_ID, END)
-
-            val margin =
-                if (splitShadeStateController.shouldUseSplitNotificationShade(context.resources)) {
-                    context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
-                } else {
-                    context.resources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) +
-                        Utils.getStatusBarHeaderHeightKeyguard(context)
-                }
-            setMargin(statusViewId, TOP, margin)
-        }
-    }
-
-    @OptIn(ExperimentalCoroutinesApi::class)
-    override fun removeViews(constraintLayout: ConstraintLayout) {
-        constraintLayout.removeView(statusViewId)
-        keyguardViewConfigurator.get().keyguardStatusViewController = null
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/KeyguardSliceViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/KeyguardSliceViewSection.kt
index 604318a..962e608 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/KeyguardSliceViewSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/KeyguardSliceViewSection.kt
@@ -17,37 +17,64 @@
 
 package com.android.systemui.keyguard.ui.view.layout.sections
 
-import android.view.View
-import android.view.ViewGroup
+import android.os.Handler
+import android.view.LayoutInflater
 import androidx.constraintlayout.widget.Barrier
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.constraintlayout.widget.ConstraintSet
+import com.android.keyguard.KeyguardSliceView
+import com.android.keyguard.KeyguardSliceViewController
 import com.android.systemui.customization.R as customR
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
 import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.settings.DisplayTracker
 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
+import com.android.systemui.statusbar.policy.ConfigurationController
 import javax.inject.Inject
 
 class KeyguardSliceViewSection
 @Inject
 constructor(
     val smartspaceController: LockscreenSmartspaceController,
+    val layoutInflater: LayoutInflater,
+    @Main val handler: Handler,
+    @Background val bgHandler: Handler,
+    val activityStarter: ActivityStarter,
+    val configurationController: ConfigurationController,
+    val dumpManager: DumpManager,
+    val displayTracker: DisplayTracker,
 ) : KeyguardSection() {
+    private lateinit var sliceView: KeyguardSliceView
+
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (smartspaceController.isEnabled) return
 
-        constraintLayout.findViewById<View?>(R.id.keyguard_slice_view)?.let {
-            (it.parent as ViewGroup).removeView(it)
-            constraintLayout.addView(it)
-        }
+        sliceView =
+            layoutInflater.inflate(R.layout.keyguard_slice_view, null, false) as KeyguardSliceView
+        constraintLayout.addView(sliceView)
     }
 
-    override fun bindData(constraintLayout: ConstraintLayout) {}
+    override fun bindData(constraintLayout: ConstraintLayout) {
+        if (smartspaceController.isEnabled) return
+
+        val controller =
+            KeyguardSliceViewController(
+                handler,
+                bgHandler,
+                sliceView,
+                activityStarter,
+                configurationController,
+                dumpManager,
+                displayTracker,
+            )
+        controller.init()
+    }
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (smartspaceController.isEnabled) return
 
         constraintSet.apply {
@@ -55,13 +82,13 @@
                 R.id.keyguard_slice_view,
                 ConstraintSet.START,
                 ConstraintSet.PARENT_ID,
-                ConstraintSet.START
+                ConstraintSet.START,
             )
             connect(
                 R.id.keyguard_slice_view,
                 ConstraintSet.END,
                 ConstraintSet.PARENT_ID,
-                ConstraintSet.END
+                ConstraintSet.END,
             )
             constrainHeight(R.id.keyguard_slice_view, ConstraintSet.WRAP_CONTENT)
 
@@ -69,20 +96,19 @@
                 R.id.keyguard_slice_view,
                 ConstraintSet.TOP,
                 customR.id.lockscreen_clock_view,
-                ConstraintSet.BOTTOM
+                ConstraintSet.BOTTOM,
             )
 
             createBarrier(
                 R.id.smart_space_barrier_bottom,
                 Barrier.BOTTOM,
                 0,
-                *intArrayOf(R.id.keyguard_slice_view)
+                *intArrayOf(R.id.keyguard_slice_view),
             )
         }
     }
 
     override fun removeViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (smartspaceController.isEnabled) return
 
         constraintLayout.removeView(R.id.keyguard_slice_view)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
index 620cc13..fc26d18 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/NotificationStackScrollLayoutSection.kt
@@ -25,7 +25,6 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
 import androidx.constraintlayout.widget.ConstraintSet.TOP
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
@@ -62,9 +61,6 @@
     }
 
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         // This moves the existing NSSL view to a different parent, as the controller is a
         // singleton and recreating it has other bad side effects.
         // In the SceneContainer, this is done by the NotificationSection composable.
@@ -78,10 +74,6 @@
     }
 
     override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         disposableHandle?.dispose()
         disposableHandle =
             sharedNotificationContainerBinder.bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
index 73e14b1..cd038d7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SmartspaceSection.kt
@@ -26,7 +26,6 @@
 import com.android.systemui.customization.R as customR
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardSmartspaceInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardSection
@@ -70,7 +69,6 @@
     }
 
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return
         smartspaceView = smartspaceController.buildAndConnectView(constraintLayout)
         weatherView = smartspaceController.buildAndConnectWeatherView(constraintLayout)
@@ -98,7 +96,6 @@
     }
 
     override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return
         disposableHandle?.dispose()
         disposableHandle =
@@ -111,13 +108,11 @@
     }
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return
         val dateWeatherPaddingStart = KeyguardSmartspaceViewModel.getDateWeatherStartMargin(context)
         val smartspaceHorizontalPadding =
             KeyguardSmartspaceViewModel.getSmartspaceHorizontalMargin(context)
         constraintSet.apply {
-            // migrate addDateWeatherView, addWeatherView from KeyguardClockSwitchController
             constrainHeight(sharedR.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT)
             constrainWidth(sharedR.id.date_smartspace_view, ConstraintSet.WRAP_CONTENT)
             connect(
@@ -128,7 +123,6 @@
                 dateWeatherPaddingStart,
             )
 
-            // migrate addSmartspaceView from KeyguardClockSwitchController
             constrainHeight(sharedR.id.bc_smartspace_view, ConstraintSet.WRAP_CONTENT)
             constrainWidth(sharedR.id.bc_smartspace_view, ConstraintSet.MATCH_CONSTRAINT)
             connect(
@@ -182,7 +176,6 @@
     }
 
     override fun removeViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) return
         if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) return
         listOf(smartspaceView, dateWeatherView).forEach {
             it?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
index f0d21f2..c91a007 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeMediaSection.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.keyguard.ui.view.layout.sections
 
 import android.content.Context
-import android.view.View
 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.widget.FrameLayout
 import androidx.constraintlayout.widget.ConstraintLayout
@@ -29,11 +28,9 @@
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import com.android.systemui.customization.R as customR
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.media.controls.ui.controller.KeyguardMediaController
 import com.android.systemui.res.R
-import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.shade.ShadeDisplayAware
 import javax.inject.Inject
 
@@ -42,20 +39,11 @@
 @Inject
 constructor(
     @ShadeDisplayAware private val context: Context,
-    private val notificationPanelView: NotificationPanelView,
     private val keyguardMediaController: KeyguardMediaController,
 ) : KeyguardSection() {
     private val mediaContainerId = R.id.status_view_media_container
 
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
-        notificationPanelView.findViewById<View>(mediaContainerId)?.let {
-            notificationPanelView.removeView(it)
-        }
-
         val mediaFrame =
             FrameLayout(context, null).apply {
                 id = mediaContainerId
@@ -75,10 +63,6 @@
     override fun bindData(constraintLayout: ConstraintLayout) {}
 
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         constraintSet.apply {
             constrainWidth(mediaContainerId, MATCH_CONSTRAINT)
             constrainHeight(mediaContainerId, WRAP_CONTENT)
@@ -89,10 +73,6 @@
     }
 
     override fun removeViews(constraintLayout: ConstraintLayout) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-
         constraintLayout.removeView(mediaContainerId)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
index 729759a..5d463f7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/SplitShadeNotificationStackScrollLayoutSection.kt
@@ -23,7 +23,6 @@
 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.res.R
 import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.shade.ShadeDisplayAware
@@ -50,16 +49,13 @@
         sharedNotificationContainerBinder,
     ) {
     override fun applyConstraints(constraintSet: ConstraintSet) {
-        if (!MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
         constraintSet.apply {
             connect(
                 R.id.nssl_placeholder,
                 TOP,
                 PARENT_ID,
                 TOP,
-                context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin)
+                context.resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin),
             )
             connect(R.id.nssl_placeholder, START, PARENT_ID, START)
             connect(R.id.nssl_placeholder, END, PARENT_ID, END)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
index 8af5b5f..1866d62 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModel.kt
@@ -23,10 +23,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
@@ -46,6 +45,7 @@
 @Inject
 constructor(
     animationFlow: KeyguardTransitionAnimationFlow,
+    blurConfig: BlurConfig,
     shadeDependentFlows: ShadeDependentFlows,
 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
     private val transitionAnimation =
@@ -82,14 +82,14 @@
     override val windowBlurRadius: Flow<Float> =
         shadeDependentFlows.transitionFlow(
             flowWhenShadeIsExpanded =
-                transitionAnimation.immediatelyTransitionTo(MAX_BACKGROUND_BLUR_RADIUS),
+                transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
             flowWhenShadeIsNotExpanded =
                 transitionAnimation.sharedFlow(
                     duration = FromAlternateBouncerTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
                     onStep = { step ->
-                        MathUtils.lerp(MIN_BACKGROUND_BLUR_RADIUS, MAX_BACKGROUND_BLUR_RADIUS, step)
+                        MathUtils.lerp(blurConfig.minBlurRadiusPx, blurConfig.maxBlurRadiusPx, step)
                     },
-                    onFinish = { MAX_BACKGROUND_BLUR_RADIUS },
+                    onFinish = { blurConfig.maxBlurRadiusPx },
                 ),
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModel.kt
deleted file mode 100644
index acaa15e..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModel.kt
+++ /dev/null
@@ -1,100 +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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
-import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
-import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
-import com.android.systemui.keyguard.shared.model.KeyguardState.UNDEFINED
-import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.scene.shared.model.Scenes
-import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combineTransform
-import kotlinx.coroutines.flow.onStart
-
-/** Models UI state for the alpha of the AOD (always-on display). */
-@SysUISingleton
-class AodAlphaViewModel
-@Inject
-constructor(
-    keyguardTransitionInteractor: KeyguardTransitionInteractor,
-    goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
-    goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
-    keyguardInteractor: KeyguardInteractor,
-    sceneInteractor: SceneInteractor,
-) {
-
-    /** The alpha level for the entire lockscreen while in AOD. */
-    val alpha: Flow<Float> =
-        if (SceneContainerFlag.isEnabled) {
-            combineTransform(
-                keyguardTransitionInteractor.transitions,
-                sceneInteractor.transitionState,
-                goneToAodTransitionViewModel.enterFromTopAnimationAlpha.onStart { emit(0f) },
-                goneToDozingTransitionViewModel.lockscreenAlpha.onStart { emit(0f) },
-                keyguardInteractor.keyguardAlpha.onStart { emit(1f) },
-            ) { step, sceneTransitionState, goneToAodAlpha, goneToDozingAlpha, keyguardAlpha ->
-                if (sceneTransitionState.isIdle(Scenes.Gone)) {
-                    emit(0f)
-                } else if (
-                    step.from == UNDEFINED &&
-                        step.to == AOD &&
-                        sceneTransitionState.isTransitioning(Scenes.Gone, Scenes.Lockscreen)
-                ) {
-                    emit(goneToAodAlpha)
-                } else if (
-                    step.from == UNDEFINED &&
-                        step.to == DOZING &&
-                        sceneTransitionState.isTransitioning(Scenes.Gone, Scenes.Lockscreen)
-                ) {
-                    emit(goneToDozingAlpha)
-                } else if (!MigrateClocksToBlueprint.isEnabled) {
-                    emit(keyguardAlpha)
-                }
-            }
-        } else {
-            combineTransform(
-                keyguardTransitionInteractor.transitions,
-                goneToAodTransitionViewModel.enterFromTopAnimationAlpha.onStart { emit(0f) },
-                goneToDozingTransitionViewModel.lockscreenAlpha.onStart { emit(0f) },
-                keyguardInteractor.keyguardAlpha.onStart { emit(1f) },
-            ) { step, goneToAodAlpha, goneToDozingAlpha, keyguardAlpha ->
-                if (step.to == GONE) {
-                    // When transitioning to GONE, only emit a value when complete as other
-                    // transitions may be controlling the alpha fade
-                    if (step.value == 1f) {
-                        emit(0f)
-                    }
-                } else if (step.from == GONE && step.to == AOD) {
-                    emit(goneToAodAlpha)
-                } else if (step.from == GONE && step.to == DOZING) {
-                    emit(goneToDozingAlpha)
-                } else if (!MigrateClocksToBlueprint.isEnabled) {
-                    emit(keyguardAlpha)
-                }
-            }
-        }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
index 1c89723..fb311a5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodBurnInViewModel.kt
@@ -24,7 +24,6 @@
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -194,12 +193,7 @@
                 (!useAltAod) && keyguardClockViewModel.clockSize.value == ClockSize.LARGE
 
             val burnInY = MathUtils.lerp(0, burnIn.translationY, interpolated).toInt()
-            val translationY =
-                if (MigrateClocksToBlueprint.isEnabled) {
-                    max(params.topInset - params.minViewY, burnInY)
-                } else {
-                    max(params.topInset, params.minViewY + burnInY) - params.minViewY
-                }
+            val translationY = max(params.topInset - params.minViewY, burnInY)
             BurnInModel(
                 translationX = MathUtils.lerp(0, burnIn.translationX, interpolated).toInt(),
                 translationY = translationY,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
index e6b796f..dbb6a49 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerTransitionViewModel.kt
@@ -22,9 +22,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -38,7 +38,7 @@
 @SysUISingleton
 class AodToPrimaryBouncerTransitionViewModel
 @Inject
-constructor(animationFlow: KeyguardTransitionAnimationFlow) :
+constructor(blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
     DeviceEntryIconTransition, PrimaryBouncerTransition {
     private val transitionAnimation =
         animationFlow
@@ -52,5 +52,5 @@
         transitionAnimation.immediatelyTransitionTo(0f)
 
     override val windowBlurRadius: Flow<Float> =
-        transitionAnimation.immediatelyTransitionTo(MAX_BACKGROUND_BLUR_RADIUS)
+        transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
index c1670c3..dff645c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModel.kt
@@ -23,10 +23,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -40,7 +39,7 @@
 @SysUISingleton
 class DozingToPrimaryBouncerTransitionViewModel
 @Inject
-constructor(animationFlow: KeyguardTransitionAnimationFlow) :
+constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
     DeviceEntryIconTransition, PrimaryBouncerTransition {
 
     private val transitionAnimation =
@@ -58,8 +57,8 @@
         transitionAnimation.sharedFlow(
             TO_PRIMARY_BOUNCER_DURATION,
             onStep = { step ->
-                MathUtils.lerp(MIN_BACKGROUND_BLUR_RADIUS, MAX_BACKGROUND_BLUR_RADIUS, step)
+                MathUtils.lerp(blurConfig.minBlurRadiusPx, blurConfig.maxBlurRadiusPx, step)
             },
-            onFinish = { MAX_BACKGROUND_BLUR_RADIUS },
+            onFinish = { blurConfig.maxBlurRadiusPx },
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index 6e30e48..8fe225a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -29,7 +29,6 @@
 import com.android.systemui.keyguard.shared.model.ClockSize
 import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.plugins.clocks.ClockPreviewConfig
-import com.android.systemui.plugins.clocks.DefaultClockFaceLayout.Companion.getSmallClockTopPadding
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
@@ -161,15 +160,14 @@
             )
 
     /** Calculates the top margin for the small clock. */
-    fun getSmallClockTopMargin(): Int =
-        getSmallClockTopPadding(
-            ClockPreviewConfig(
+    fun getSmallClockTopMargin(): Int {
+        return ClockPreviewConfig(
                 context,
                 shadeInteractor.isShadeLayoutWide.value,
                 SceneContainerFlag.isEnabled,
-            ),
-            systemBarUtils.getStatusBarHeaderHeightKeyguard(),
-        )
+            )
+            .getSmallClockTopPadding(systemBarUtils.getStatusBarHeaderHeightKeyguard())
+    }
 
     val smallClockTopMargin =
         combine(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
index 4663a2b..3dcc60a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardIndicationAreaViewModel.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.doze.util.BurnInHelperWrapper
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -72,8 +71,8 @@
         combine(shortcutsCombinedViewModel.startButton, shortcutsCombinedViewModel.endButton) {
                 startButtonModel,
                 endButtonModel ->
-            startButtonModel.isVisible || endButtonModel.isVisible
-        }
+                startButtonModel.isVisible || endButtonModel.isVisible
+            }
             .distinctUntilChanged()
 
     @OptIn(ExperimentalCoroutinesApi::class)
@@ -101,18 +100,6 @@
 
     /** Returns an observable for the y-offset by which the indication area should be translated. */
     fun indicationAreaTranslationY(defaultBurnInOffset: Int): Flow<Float> {
-        return if (MigrateClocksToBlueprint.isEnabled) {
-            burnIn.map { it.translationY.toFloat() }.flowOn(mainDispatcher)
-        } else {
-            keyguardInteractor.dozeAmount
-                .map { dozeAmount ->
-                    dozeAmount *
-                        (burnInHelperWrapper.burnInOffset(
-                            /* amplitude = */ defaultBurnInOffset * 2,
-                            /* xAxis= */ false,
-                        ) - defaultBurnInOffset)
-                }
-                .distinctUntilChanged()
-        }
+        return burnIn.map { it.translationY.toFloat() }.flowOn(mainDispatcher)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
index 15b696e..f6c66d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardPreviewSmartspaceViewModel.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
 import com.android.systemui.keyguard.shared.model.ClockSizeSetting
 import com.android.systemui.plugins.clocks.ClockPreviewConfig
-import com.android.systemui.plugins.clocks.DefaultClockFaceLayout.Companion.getSmallClockTopPadding
 import com.android.systemui.statusbar.ui.SystemBarUtilsProxy
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
@@ -74,14 +73,13 @@
      * SmallClockTopPadding decides the top position of smartspace
      */
     fun getSmallClockSmartspaceTopPadding(config: ClockPreviewConfig): Int {
-        return getSmallClockTopPadding(config, systemBarUtils.getStatusBarHeaderHeightKeyguard()) +
-            config.previewContext.resources.getDimensionPixelSize(customR.dimen.small_clock_height)
+        return config.getSmallClockTopPadding(systemBarUtils.getStatusBarHeaderHeightKeyguard()) +
+            config.context.resources.getDimensionPixelSize(customR.dimen.small_clock_height)
     }
 
     fun getLargeClockSmartspaceTopPadding(clockPreviewConfig: ClockPreviewConfig): Int {
-        return getSmallClockTopPadding(
-            clockPreviewConfig,
-            systemBarUtils.getStatusBarHeaderHeightKeyguard(),
+        return clockPreviewConfig.getSmallClockTopPadding(
+            systemBarUtils.getStatusBarHeaderHeightKeyguard()
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceHapticViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceHapticViewModel.kt
new file mode 100644
index 0000000..890628c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordanceHapticViewModel.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+class KeyguardQuickAffordanceHapticViewModel
+@AssistedInject
+constructor(
+    @Assisted quickAffordanceViewModel: Flow<KeyguardQuickAffordanceViewModel>,
+    private val quickAffordanceInteractor: KeyguardQuickAffordanceInteractor,
+) {
+
+    private val activatedHistory = MutableStateFlow(ActivatedHistory(false))
+
+    private val launchingHapticState: Flow<HapticState> =
+        combine(
+                quickAffordanceViewModel.map { it.configKey },
+                quickAffordanceInteractor.launchingFromTriggeredResult,
+            ) { key, launchingResult ->
+                val validKey = key != null && key == launchingResult?.configKey
+                if (validKey && launchingResult?.launched == true) {
+                    HapticState.LAUNCH
+                } else {
+                    HapticState.NO_HAPTICS
+                }
+            }
+            .distinctUntilChanged()
+
+    private val toggleHapticState: Flow<HapticState> =
+        activatedHistory
+            .map { history ->
+                when {
+                    history.previousValue == false && history.currentValue -> HapticState.TOGGLE_ON
+                    history.previousValue == true && !history.currentValue -> HapticState.TOGGLE_OFF
+                    else -> HapticState.NO_HAPTICS
+                }
+            }
+            .distinctUntilChanged()
+
+    val quickAffordanceHapticState =
+        merge(launchingHapticState, toggleHapticState).distinctUntilChanged()
+
+    fun resetLaunchingFromTriggeredResult() =
+        quickAffordanceInteractor.setLaunchingFromTriggeredResult(null)
+
+    fun updateActivatedHistory(isActivated: Boolean) {
+        activatedHistory.value =
+            ActivatedHistory(
+                currentValue = isActivated,
+                previousValue = activatedHistory.value.currentValue,
+            )
+    }
+
+    enum class HapticState {
+        TOGGLE_ON,
+        TOGGLE_OFF,
+        LAUNCH,
+        NO_HAPTICS,
+    }
+
+    private data class ActivatedHistory(
+        val currentValue: Boolean,
+        val previousValue: Boolean? = null,
+    )
+
+    @AssistedFactory
+    interface Factory {
+        fun create(
+            quickAffordanceViewModel: Flow<KeyguardQuickAffordanceViewModel>
+        ): KeyguardQuickAffordanceHapticViewModel
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index 9066d46..eaba5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -29,7 +29,6 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.domain.interactor.PulseExpansionInteractor
 import com.android.systemui.keyguard.shared.model.Edge
-import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
@@ -130,7 +129,6 @@
         PrimaryBouncerToLockscreenTransitionViewModel,
     private val screenOffAnimationController: ScreenOffAnimationController,
     private val aodBurnInViewModel: AodBurnInViewModel,
-    private val aodAlphaViewModel: AodAlphaViewModel,
     private val shadeInteractor: ShadeInteractor,
 ) {
     val burnInLayerVisibility: Flow<Int> =
@@ -284,15 +282,6 @@
             .distinctUntilChanged()
     }
 
-    /** Specific alpha value for elements visible during [KeyguardState.LOCKSCREEN] */
-    @Deprecated("only used for legacy status view")
-    fun lockscreenStateAlpha(viewState: ViewStateAccessor): Flow<Float> {
-        return aodToLockscreenTransitionViewModel.lockscreenAlpha(viewState)
-    }
-
-    /** For elements that appear and move during the animation -> AOD */
-    val burnInLayerAlpha: Flow<Float> = aodAlphaViewModel.alpha
-
     val translationY: Flow<Float> = aodBurnInViewModel.movement.map { it.translationY.toFloat() }
 
     val translationX: Flow<StateToValue> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
index 48cc8ad..182c847 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModel.kt
@@ -23,10 +23,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.ui.composable.transitions.TO_BOUNCER_FADE_FRACTION
@@ -44,6 +43,7 @@
 class LockscreenToPrimaryBouncerTransitionViewModel
 @Inject
 constructor(
+    private val blurConfig: BlurConfig,
     shadeDependentFlows: ShadeDependentFlows,
     animationFlow: KeyguardTransitionAnimationFlow,
 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
@@ -85,12 +85,12 @@
     override val windowBlurRadius: Flow<Float> =
         shadeDependentFlows.transitionFlow(
             flowWhenShadeIsExpanded =
-                transitionAnimation.immediatelyTransitionTo(MAX_BACKGROUND_BLUR_RADIUS),
+                transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
             flowWhenShadeIsNotExpanded =
                 transitionAnimation.sharedFlow(
                     duration = FromLockscreenTransitionInteractor.TO_PRIMARY_BOUNCER_DURATION,
                     onStep = {
-                        MathUtils.lerp(MIN_BACKGROUND_BLUR_RADIUS, MAX_BACKGROUND_BLUR_RADIUS, it)
+                        MathUtils.lerp(blurConfig.minBlurRadiusPx, blurConfig.maxBlurRadiusPx, it)
                     },
                 ),
         )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
index f14144e..92daed4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModel.kt
@@ -24,10 +24,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
@@ -45,6 +44,7 @@
 class PrimaryBouncerToAodTransitionViewModel
 @Inject
 constructor(
+    private val blurConfig: BlurConfig,
     deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
     animationFlow: KeyguardTransitionAnimationFlow,
 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
@@ -84,8 +84,8 @@
         transitionAnimation.sharedFlow(
             duration = FromPrimaryBouncerTransitionInteractor.TO_AOD_DURATION,
             onStep = { step ->
-                MathUtils.lerp(MAX_BACKGROUND_BLUR_RADIUS, MIN_BACKGROUND_BLUR_RADIUS, step)
+                MathUtils.lerp(blurConfig.maxBlurRadiusPx, blurConfig.minBlurRadiusPx, step)
             },
-            onFinish = { MIN_BACKGROUND_BLUR_RADIUS },
+            onFinish = { blurConfig.minBlurRadiusPx },
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
index a24ed26..2c5250b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModel.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.ui.viewmodel
 
+import android.util.MathUtils
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_DOZING_DURATION
@@ -23,6 +24,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
 import com.android.systemui.scene.shared.model.Scenes
@@ -41,6 +43,7 @@
 class PrimaryBouncerToDozingTransitionViewModel
 @Inject
 constructor(
+    private val blurConfig: BlurConfig,
     deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
     animationFlow: KeyguardTransitionAnimationFlow,
 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
@@ -67,7 +70,11 @@
         }
 
     override val windowBlurRadius: Flow<Float> =
-        transitionAnimation.immediatelyTransitionTo(
-            PrimaryBouncerTransition.MIN_BACKGROUND_BLUR_RADIUS
+        transitionAnimation.sharedFlow(
+            duration = TO_DOZING_DURATION,
+            onStep = { step ->
+                MathUtils.lerp(blurConfig.maxBlurRadiusPx, blurConfig.minBlurRadiusPx, step)
+            },
+            onFinish = { blurConfig.minBlurRadiusPx },
         )
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
index b52a390..3636b74 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModel.kt
@@ -22,16 +22,16 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 
 @SysUISingleton
 class PrimaryBouncerToGlanceableHubTransitionViewModel
 @Inject
-constructor(animationFlow: KeyguardTransitionAnimationFlow) :
+constructor(private val blurConfig: BlurConfig, animationFlow: KeyguardTransitionAnimationFlow) :
     DeviceEntryIconTransition, PrimaryBouncerTransition {
     private val transitionAnimation =
         animationFlow
@@ -42,5 +42,5 @@
         transitionAnimation.immediatelyTransitionTo(1f)
 
     override val windowBlurRadius: Flow<Float> =
-        transitionAnimation.immediatelyTransitionTo(MIN_BACKGROUND_BLUR_RADIUS)
+        transitionAnimation.immediatelyTransitionTo(blurConfig.minBlurRadiusPx)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
index 713ac15..ae155ba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -28,9 +28,8 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.shared.model.ScrimAlpha
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.statusbar.SysuiStatusBarStateController
 import dagger.Lazy
 import javax.inject.Inject
@@ -48,6 +47,7 @@
 class PrimaryBouncerToGoneTransitionViewModel
 @Inject
 constructor(
+    private val blurConfig: BlurConfig,
     private val statusBarStateController: SysuiStatusBarStateController,
     private val primaryBouncerInteractor: PrimaryBouncerInteractor,
     keyguardDismissActionInteractor: Lazy<KeyguardDismissActionInteractor>,
@@ -116,9 +116,9 @@
             onStart = { willRunDismissFromKeyguard = willRunAnimationOnKeyguard() },
             onStep = {
                 if (willRunDismissFromKeyguard) {
-                    MIN_BACKGROUND_BLUR_RADIUS
+                    blurConfig.minBlurRadiusPx
                 } else {
-                    MathUtils.lerp(MAX_BACKGROUND_BLUR_RADIUS, MIN_BACKGROUND_BLUR_RADIUS, it)
+                    MathUtils.lerp(blurConfig.maxBlurRadiusPx, blurConfig.minBlurRadiusPx, it)
                 }
             },
         )
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
index e737fce..1b1718d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModel.kt
@@ -24,10 +24,9 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
 import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MAX_BACKGROUND_BLUR_RADIUS
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition.Companion.MIN_BACKGROUND_BLUR_RADIUS
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
@@ -43,6 +42,7 @@
 class PrimaryBouncerToLockscreenTransitionViewModel
 @Inject
 constructor(
+    private val blurConfig: BlurConfig,
     animationFlow: KeyguardTransitionAnimationFlow,
     shadeDependentFlows: ShadeDependentFlows,
 ) : DeviceEntryIconTransition, PrimaryBouncerTransition {
@@ -78,12 +78,12 @@
     override val windowBlurRadius: Flow<Float> =
         shadeDependentFlows.transitionFlow(
             flowWhenShadeIsExpanded =
-                transitionAnimation.immediatelyTransitionTo(MAX_BACKGROUND_BLUR_RADIUS),
+                transitionAnimation.immediatelyTransitionTo(blurConfig.maxBlurRadiusPx),
             flowWhenShadeIsNotExpanded =
                 transitionAnimation.sharedFlow(
                     duration = FromPrimaryBouncerTransitionInteractor.TO_LOCKSCREEN_DURATION,
                     onStep = {
-                        MathUtils.lerp(MAX_BACKGROUND_BLUR_RADIUS, MIN_BACKGROUND_BLUR_RADIUS, it)
+                        MathUtils.lerp(blurConfig.maxBlurRadiusPx, blurConfig.minBlurRadiusPx, it)
                     },
                 ),
         )
diff --git a/packages/SystemUI/src/com/android/systemui/lottie/LottieTaskExt.kt b/packages/SystemUI/src/com/android/systemui/lottie/LottieTaskExt.kt
new file mode 100644
index 0000000..dd2525f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/lottie/LottieTaskExt.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.lottie
+
+import com.airbnb.lottie.LottieComposition
+import com.airbnb.lottie.LottieListener
+import com.airbnb.lottie.LottieTask
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+/**
+ * Suspends until [LottieTask] is finished with a result or a failure.
+ *
+ * @return result of the [LottieTask] when it's successful
+ */
+suspend fun LottieTask<LottieComposition>.await() =
+    suspendCancellableCoroutine<LottieComposition> { continuation ->
+        val resultListener =
+            LottieListener<LottieComposition> { result ->
+                with(continuation) { if (!isCancelled && !isCompleted) resume(result) }
+            }
+        val failureListener =
+            LottieListener<Throwable> { throwable ->
+                with(continuation) {
+                    if (!isCancelled && !isCompleted) resumeWithException(throwable)
+                }
+            }
+        addListener(resultListener)
+        addFailureListener(failureListener)
+        continuation.invokeOnCancellation {
+            removeListener(resultListener)
+            removeFailureListener(failureListener)
+        }
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
index 9bea6e9..520cc23 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/KeyguardMediaController.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.Dumpable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.media.dagger.MediaModule.KEYGUARD
@@ -114,15 +113,6 @@
 
     var visibilityChangedListener: ((Boolean) -> Unit)? = null
 
-    /**
-     * Whether the doze wake up animation is delayed and we are currently waiting for it to start.
-     */
-    var isDozeWakeUpAnimationWaiting: Boolean = false
-        set(value) {
-            field = value
-            refreshMediaPosition(reason = "isDozeWakeUpAnimationWaiting changed")
-        }
-
     /** single pane media container placed at the top of the notifications list */
     var singlePaneContainer: MediaContainerView? = null
         private set
@@ -150,7 +140,7 @@
         refreshMediaPosition(reason = "onMediaHostVisibilityChanged")
 
         if (visible) {
-            if (MigrateClocksToBlueprint.isEnabled && useSplitShade) {
+            if (useSplitShade) {
                 return
             }
             mediaHost.hostView.layoutParams.apply {
@@ -241,13 +231,7 @@
         // by the clock. This is not the case for single-line clock though.
         // For single shade, we don't need to do it, because media is a child of NSSL, which already
         // gets hidden on AOD.
-        // Media also has to be hidden when waking up from dozing, and the doze wake up animation is
-        // delayed and waiting to be started.
-        // This is to stay in sync with the delaying of the horizontal alignment of the rest of the
-        // keyguard container, that is also delayed until the "wait" is over.
-        // If we show media during this waiting period, the shade will still be centered, and using
-        // the entire width of the screen, and making media show fully stretched.
-        return !statusBarStateController.isDozing && !isDozeWakeUpAnimationWaiting
+        return !statusBarStateController.isDozing
     }
 
     private fun showMediaPlayer() {
@@ -291,18 +275,17 @@
                 println("visible", visible)
                 println("useSplitShade", useSplitShade)
                 println("bypassController.bypassEnabled", bypassController.bypassEnabled)
-                println("isDozeWakeUpAnimationWaiting", isDozeWakeUpAnimationWaiting)
                 println("singlePaneContainer", singlePaneContainer)
                 println("splitShadeContainer", splitShadeContainer)
                 if (lastUsedStatusBarState != -1) {
                     println(
                         "lastUsedStatusBarState",
-                        StatusBarState.toString(lastUsedStatusBarState)
+                        StatusBarState.toString(lastUsedStatusBarState),
                     )
                 }
                 println(
                     "statusBarStateController.state",
-                    StatusBarState.toString(statusBarStateController.state)
+                    StatusBarState.toString(statusBarStateController.state),
                 )
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index c32bd40..b4dabbe 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -34,13 +34,14 @@
 import android.view.ViewGroupOverlay
 import androidx.annotation.VisibleForTesting
 import com.android.app.animation.Interpolators
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.app.tracing.traceSection
 import com.android.keyguard.KeyguardViewController
 import com.android.systemui.Flags.mediaControlsLockscreenShadeBugFix
 import com.android.systemui.communal.ui.viewmodel.CommunalTransitionViewModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dreams.DreamOverlayStateController
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -68,7 +69,6 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.mapLatest
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 private val TAG: String = MediaHierarchyManager::class.java.simpleName
 
@@ -115,7 +115,7 @@
     wakefulnessLifecycle: WakefulnessLifecycle,
     shadeInteractor: ShadeInteractor,
     private val secureSettings: SecureSettings,
-    @Main private val handler: Handler,
+    @Background private val handler: Handler,
     @Application private val coroutineScope: CoroutineScope,
     private val splitShadeStateController: SplitShadeStateController,
     private val logger: MediaViewLogger,
@@ -631,7 +631,7 @@
                     }
                 }
             }
-        secureSettings.registerContentObserverForUserSync(
+        secureSettings.registerContentObserverForUserAsync(
             Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
             settingsObserver,
             UserHandle.USER_ALL,
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 742f435..0ada931 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -98,7 +98,7 @@
                 ((MediaGroupDividerViewHolder) viewHolder).onBind(currentMediaItem.getTitle());
                 break;
             case MediaItem.MediaItemType.TYPE_PAIR_NEW_DEVICE:
-                ((MediaDeviceViewHolder) viewHolder).onBind(CUSTOMIZED_ITEM_PAIR_NEW);
+                ((MediaDeviceViewHolder) viewHolder).onBindPairNewDevice();
                 break;
             case MediaItem.MediaItemType.TYPE_DEVICE:
                 ((MediaDeviceViewHolder) viewHolder).onBind(
@@ -418,20 +418,18 @@
             updateIconAreaClickListener(listener);
         }
 
-        @Override
-        void onBind(int customizedItem) {
-            if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
-                mTitleText.setTextColor(mController.getColorItemContent());
-                mCheckBox.setVisibility(View.GONE);
-                setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new));
-                final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
-                mTitleIcon.setImageDrawable(addDrawable);
-                mTitleIcon.setImageTintList(
-                        ColorStateList.valueOf(mController.getColorItemContent()));
-                mIconAreaLayout.setBackgroundTintList(
-                        ColorStateList.valueOf(mController.getColorItemBackground()));
-                mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
-            }
+        /** Binds a ViewHolder for a "Connect a device" item. */
+        void onBindPairNewDevice() {
+            mTitleText.setTextColor(mController.getColorItemContent());
+            mCheckBox.setVisibility(View.GONE);
+            setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new));
+            final Drawable addDrawable = mContext.getDrawable(R.drawable.ic_add);
+            mTitleIcon.setImageDrawable(addDrawable);
+            mTitleIcon.setImageTintList(
+                    ColorStateList.valueOf(mController.getColorItemContent()));
+            mIconAreaLayout.setBackgroundTintList(
+                    ColorStateList.valueOf(mController.getColorItemBackground()));
+            mContainerLayout.setOnClickListener(mController::launchBluetoothPairing);
         }
 
         private void onGroupActionTriggered(boolean isChecked, MediaDevice device) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 574ccee..af37eea 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -20,7 +20,6 @@
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
-import android.annotation.DrawableRes;
 import android.app.WallpaperColors;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -60,10 +59,6 @@
 public abstract class MediaOutputBaseAdapter extends
         RecyclerView.Adapter<RecyclerView.ViewHolder> {
 
-    static final int CUSTOMIZED_ITEM_PAIR_NEW = 1;
-    static final int CUSTOMIZED_ITEM_GROUP = 2;
-    static final int CUSTOMIZED_ITEM_DYNAMIC_GROUP = 3;
-
     protected final MediaSwitchingController mController;
 
     private static final int UNMUTE_DEFAULT_VOLUME = 2;
@@ -197,8 +192,6 @@
                     ColorStateList.valueOf(mController.getColorSeekbarProgress()));
         }
 
-        abstract void onBind(int customizedItem);
-
         void setSingleLineLayout(CharSequence title) {
             setSingleLineLayout(title, false, false, false, false);
         }
@@ -366,7 +359,6 @@
                                     / (double) seekBar.getMax());
                     mVolumeValueText.setText(mContext.getResources().getString(
                             R.string.media_output_dialog_volume_percentage, percentage));
-                    mVolumeValueText.setVisibility(View.VISIBLE);
                     if (mStartFromMute) {
                         updateUnmutedVolumeIcon(device);
                         mStartFromMute = false;
@@ -457,32 +449,6 @@
                     ColorStateList.valueOf(mController.getColorConnectedItemBackground()));
         }
 
-        private void animateCornerAndVolume(int fromProgress, int toProgress) {
-            final GradientDrawable layoutBackgroundDrawable =
-                    (GradientDrawable) mItemLayout.getBackground();
-            final ClipDrawable clipDrawable =
-                    (ClipDrawable) ((LayerDrawable) mSeekBar.getProgressDrawable())
-                            .findDrawableByLayerId(android.R.id.progress);
-            final GradientDrawable targetBackgroundDrawable =
-                    (GradientDrawable) (mIconAreaLayout.getBackground());
-            mCornerAnimator.addUpdateListener(animation -> {
-                float value = (float) animation.getAnimatedValue();
-                layoutBackgroundDrawable.setCornerRadius(value);
-                if (toProgress == 0) {
-                    targetBackgroundDrawable.setCornerRadius(value);
-                } else {
-                    targetBackgroundDrawable.setCornerRadii(new float[]{
-                            value,
-                            value,
-                            0, 0, 0, 0, value, value
-                    });
-                }
-            });
-            mVolumeAnimator.setIntValues(fromProgress, toProgress);
-            mVolumeAnimator.start();
-            mCornerAnimator.start();
-        }
-
         private void initAnimator() {
             mCornerAnimator = ValueAnimator.ofFloat(mController.getInactiveRadius(),
                     mController.getActiveRadius());
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 6bc995f3..64256f9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -26,13 +26,9 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
@@ -70,7 +66,6 @@
         implements MediaSwitchingController.Callback, Window.Callback {
 
     private static final String TAG = "MediaOutputDialog";
-    private static final String EMPTY_TITLE = " ";
     private static final String PREF_NAME = "MediaOutputDialog";
     private static final String PREF_IS_LE_BROADCAST_FIRST_LAUNCH = "PrefIsLeBroadcastFirstLaunch";
     private static final boolean DEBUG = true;
@@ -99,11 +94,9 @@
     private ImageView mBroadcastIcon;
     private RecyclerView mDevicesRecyclerView;
     private LinearLayout mDeviceListLayout;
-    private LinearLayout mCastAppLayout;
     private LinearLayout mMediaMetadataSectionLayout;
     private Button mDoneButton;
     private Button mStopButton;
-    private Button mAppButton;
     private int mListMaxHeight;
     private int mItemHeight;
     private int mListPaddingTop;
@@ -262,9 +255,7 @@
         mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
         mDoneButton = mDialogView.requireViewById(R.id.done);
         mStopButton = mDialogView.requireViewById(R.id.stop);
-        mAppButton = mDialogView.requireViewById(R.id.launch_app_button);
         mAppResourceIcon = mDialogView.requireViewById(R.id.app_source_icon);
-        mCastAppLayout = mDialogView.requireViewById(R.id.cast_app_section);
         mBroadcastIcon = mDialogView.requireViewById(R.id.broadcast_icon);
 
         mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
@@ -277,9 +268,11 @@
         // Init bottom buttons
         mDoneButton.setOnClickListener(v -> dismiss());
         mStopButton.setOnClickListener(v -> onStopButtonClick());
-        mAppButton.setOnClickListener(mMediaSwitchingController::tryToLaunchMediaApplication);
-        mMediaMetadataSectionLayout.setOnClickListener(
-                mMediaSwitchingController::tryToLaunchMediaApplication);
+        if (mMediaSwitchingController.getAppLaunchIntent() != null) {
+            // For a11y purposes only add listener if a section is clickable.
+            mMediaMetadataSectionLayout.setOnClickListener(
+                    mMediaSwitchingController::tryToLaunchMediaApplication);
+        }
 
         mDismissing = false;
     }
@@ -333,8 +326,6 @@
         final IconCompat headerIcon = getHeaderIcon();
         final IconCompat appSourceIcon = getAppSourceIcon();
         boolean colorSetUpdated = false;
-        mCastAppLayout.setVisibility(
-                mMediaSwitchingController.shouldShowLaunchSection() ? View.VISIBLE : View.GONE);
         if (iconRes != 0) {
             mHeaderIcon.setVisibility(View.VISIBLE);
             mHeaderIcon.setImageResource(iconRes);
@@ -384,7 +375,6 @@
                     R.dimen.media_output_dialog_header_icon_padding);
             mHeaderIcon.setLayoutParams(new LinearLayout.LayoutParams(size + padding, size));
         }
-        mAppButton.setText(mMediaSwitchingController.getAppSourceName());
 
         if (!mIncludePlaybackAndAppMetadata) {
             mHeaderTitle.setVisibility(View.GONE);
@@ -443,22 +433,6 @@
         mDeviceListLayout.setBackgroundColor(mMediaSwitchingController.getColorDialogBackground());
     }
 
-    private Drawable resizeDrawable(Drawable drawable, int size) {
-        if (drawable == null) {
-            return null;
-        }
-        int width = drawable.getIntrinsicWidth();
-        int height = drawable.getIntrinsicHeight();
-        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
-                : Bitmap.Config.RGB_565;
-        Bitmap bitmap = Bitmap.createBitmap(width, height, config);
-        Canvas canvas = new Canvas(bitmap);
-        drawable.setBounds(0, 0, width, height);
-        drawable.draw(canvas);
-        return new BitmapDrawable(mContext.getResources(),
-                Bitmap.createScaledBitmap(bitmap, size, size, false));
-    }
-
     public void handleLeBroadcastStarted() {
         // Waiting for the onBroadcastMetadataChanged. The UI launchs the broadcast dialog when
         // the metadata is ready.
@@ -602,9 +576,6 @@
         mBroadcastSender.closeSystemDialogs();
     }
 
-    void onHeaderIconClick() {
-    }
-
     View getDialogView() {
         return mDialogView;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
index 8fbbb8b..1dbb317 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSwitchingController.java
@@ -305,11 +305,6 @@
         }
     }
 
-    boolean shouldShowLaunchSection() {
-        // TODO(b/231398073): Implements this when available.
-        return false;
-    }
-
     public boolean isRefreshing() {
         return mIsRefreshing;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepository.kt b/packages/SystemUI/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepository.kt
index debb667..a19c9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediarouter/data/repository/MediaRouterRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.mediarouter.data.repository
 
+import android.media.projection.StopReason
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.LogBuffer
@@ -40,7 +41,7 @@
     val castDevices: StateFlow<List<CastDevice>>
 
     /** Stops the cast to the given device. */
-    fun stopCasting(device: CastDevice)
+    fun stopCasting(device: CastDevice, @StopReason stopReason: Int)
 }
 
 @SysUISingleton
@@ -67,8 +68,8 @@
             .map { it.filter { device -> device.origin == CastDevice.CastOrigin.MediaRouter } }
             .stateIn(scope, SharingStarted.WhileSubscribed(), emptyList())
 
-    override fun stopCasting(device: CastDevice) {
-        castController.stopCasting(device)
+    override fun stopCasting(device: CastDevice, @StopReason stopReason: Int) {
+        castController.stopCasting(device, stopReason)
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 037a1b2..1c94f56 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -23,7 +23,6 @@
 
 import static com.android.systemui.Flags.edgebackGestureHandlerGetRunningTasksBackground;
 import static com.android.systemui.classifier.Classifier.BACK_GESTURE;
-import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
 import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED;
 import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted;
@@ -1091,8 +1090,7 @@
             boolean isBackAllowedCommon = !mDisabledForQuickstep && mIsBackGestureAllowed
                     && !mGestureBlockingActivityRunning.get()
                     && !QuickStepContract.isBackGestureDisabled(mSysUiFlags,
-                            mIsTrackpadThreeFingerSwipe)
-                    && !isTrackpadScroll(ev);
+                            mIsTrackpadThreeFingerSwipe);
             if (mIsTrackpadThreeFingerSwipe) {
                 // Trackpad back gestures don't have zones, so we don't need to check if the down
                 // event is within insets.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
index b46f2d2..1771a97 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/Utilities.java
@@ -18,16 +18,11 @@
 
 import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
 import static android.view.MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE;
-import static android.view.MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
 
 import android.view.MotionEvent;
 
 public final class Utilities {
 
-    public static boolean isTrackpadScroll(MotionEvent event) {
-        return event.getClassification() == CLASSIFICATION_TWO_FINGER_SWIPE;
-    }
-
     public static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
         return event.getClassification() == CLASSIFICATION_MULTI_FINGER_SWIPE
                 && event.getAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
index 311cbfb..b2696aea 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -132,7 +132,7 @@
         val isDefaultNotesAppSet =
             noteTaskInfoResolver.resolveInfo(
                 QUICK_AFFORDANCE,
-                user = controller.getUserForHandlingNotesTaking(QUICK_AFFORDANCE)
+                user = controller.getUserForHandlingNotesTaking(QUICK_AFFORDANCE),
             ) != null
         return when {
             isEnabled && isDefaultNotesAppSet -> PickerScreenState.Default()
@@ -158,7 +158,7 @@
 
     override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
         controller.showNoteTask(entryPoint = QUICK_AFFORDANCE)
-        return OnTriggeredResult.Handled
+        return OnTriggeredResult.Handled(true)
     }
 }
 
@@ -194,7 +194,7 @@
     fun isDefaultNotesAppSetForUser() =
         noteTaskInfoResolver.resolveInfo(
             QUICK_AFFORDANCE,
-            user = noteTaskController.getUserForHandlingNotesTaking(QUICK_AFFORDANCE)
+            user = noteTaskController.getUserForHandlingNotesTaking(QUICK_AFFORDANCE),
         ) != null
 
     trySendBlocking(isDefaultNotesAppSetForUser())
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
index 2f7e916..9ff0915 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.kt
@@ -21,15 +21,16 @@
 import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.ViewModelProvider
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.compose.theme.PlatformTheme
 import com.android.systemui.people.ui.compose.PeopleScreen
 import com.android.systemui.people.ui.viewmodel.PeopleViewModel
 import javax.inject.Inject
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** People Tile Widget configuration activity that shows the user their conversation tiles. */
 class PeopleSpaceActivity
@@ -37,6 +38,8 @@
 constructor(private val viewModelFactory: PeopleViewModel.Factory) : ComponentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
+        enableEdgeToEdge()
+
         setResult(RESULT_CANCELED)
 
         // Update the widget ID coming from the intent.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index 91a3120..1e608af1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -67,6 +67,7 @@
 import com.android.systemui.res.R
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.util.DeviceConfigProxy
@@ -141,7 +142,6 @@
 class FgsManagerControllerImpl
 @Inject
 constructor(
-    @ShadeDisplayAware private val context: Context,
     @ShadeDisplayAware private val resources: Resources,
     @Main private val mainExecutor: Executor,
     @Background private val backgroundExecutor: Executor,
@@ -155,6 +155,7 @@
     private val broadcastDispatcher: BroadcastDispatcher,
     private val dumpManager: DumpManager,
     private val systemUIDialogFactory: SystemUIDialog.Factory,
+    private val shadeDialogContextRepository: ShadeDialogContextInteractor,
 ) : Dumpable, FgsManagerController {
 
     companion object {
@@ -388,7 +389,7 @@
     override fun showDialog(expandable: Expandable?) {
         synchronized(lock) {
             if (dialog == null) {
-                val dialog = systemUIDialogFactory.create(context)
+                val dialog = systemUIDialogFactory.create(shadeDialogContextRepository.context)
                 dialog.setTitle(R.string.fgs_manager_dialog_title)
                 dialog.setMessage(R.string.fgs_manager_dialog_message)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileIcon.kt b/packages/SystemUI/src/com/android/systemui/qs/QSTileIcon.kt
index ef7e7eb..84b995e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileIcon.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileIcon.kt
@@ -22,16 +22,21 @@
 
 /**
  * Creates a [QSTile.Icon] from an [Icon].
- * * [Icon.Loaded] -> [QSTileImpl.DrawableIcon]
+ * * [Icon.Loaded] with null [res] -> [QSTileImpl.DrawableIcon]
+ * * [Icon.Loaded] & with non null [res] -> [QSTileImpl.DrawableIconWithRes]
  * * [Icon.Resource] -> [QSTileImpl.ResourceIcon]
  */
 fun Icon.asQSTileIcon(): QSTile.Icon {
     return when (this) {
         is Icon.Loaded -> {
-            QSTileImpl.DrawableIcon(this.drawable)
+            if (res == null) {
+                QSTileImpl.DrawableIcon(drawable)
+            } else {
+                QSTileImpl.DrawableIconWithRes(drawable, res)
+            }
         }
         is Icon.Resource -> {
-            QSTileImpl.ResourceIcon.get(this.res)
+            QSTileImpl.ResourceIcon.get(res)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
index f0f46d3..266e875 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
@@ -19,7 +19,7 @@
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.ContentScope
 import com.android.systemui.qs.shared.ui.ElementKeys
 
 /**
@@ -27,7 +27,7 @@
  * able to have relative anchor translation of elements that appear in QS.
  */
 @Composable
-fun SceneScope.GridAnchor(modifier: Modifier = Modifier) {
+fun ContentScope.GridAnchor(modifier: Modifier = Modifier) {
     // The size of this anchor does not matter, as the tiles don't change size on expansion.
     Spacer(modifier.element(ElementKeys.GridAnchor))
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/NotificationScrimClip.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/NotificationScrimClip.kt
index 790793e..3049a40 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/NotificationScrimClip.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/NotificationScrimClip.kt
@@ -17,16 +17,16 @@
 package com.android.systemui.qs.composefragment.ui
 
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithCache
+import androidx.compose.ui.draw.drawWithContent
 import androidx.compose.ui.geometry.CornerRadius
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.BlendMode
 import androidx.compose.ui.graphics.ClipOp
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.CompositingStrategy
 import androidx.compose.ui.graphics.drawscope.clipRect
-import androidx.compose.ui.graphics.layer.CompositingStrategy
-import androidx.compose.ui.graphics.layer.drawLayer
+import androidx.compose.ui.graphics.graphicsLayer
 
 /**
  * Clipping modifier for clipping out the notification scrim as it slides over QS. It will clip out
@@ -34,16 +34,16 @@
  * from the QS container.
  */
 fun Modifier.notificationScrimClip(clipParams: () -> NotificationScrimClipParams): Modifier {
-    return this.drawWithCache {
+    return this.graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen }
+        .drawWithContent {
+            drawContent()
             val params = clipParams()
             val left = -params.leftInset.toFloat()
             val right = size.width + params.rightInset.toFloat()
             val top = params.top.toFloat()
             val bottom = params.bottom.toFloat()
-            val graphicsLayer = obtainGraphicsLayer()
-            graphicsLayer.compositingStrategy = CompositingStrategy.Offscreen
-            graphicsLayer.record {
-                drawContent()
+            val clipSize = Size(right - left, bottom - top)
+            if (!clipSize.isEmpty()) {
                 clipRect {
                     drawRoundRect(
                         color = Color.Black,
@@ -54,9 +54,6 @@
                     )
                 }
             }
-            onDrawWithContent {
-                drawLayer(graphicsLayer)
-            }
         }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 873059e..e7fa271 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -675,17 +675,11 @@
         }
 
         private void add() {
-            if (addFromPosition(getLayoutPosition())) {
-                itemView.announceForAccessibility(
-                        itemView.getContext().getText(R.string.accessibility_qs_edit_tile_added));
-            }
+            addFromPosition(getLayoutPosition());
         }
 
         private void remove() {
-            if (removeFromPosition(getLayoutPosition())) {
-                itemView.announceForAccessibility(
-                        itemView.getContext().getText(R.string.accessibility_qs_edit_tile_removed));
-            }
+            removeFromPosition(getLayoutPosition());
         }
 
         boolean isCurrentTile() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
index b9994d7..c9d767e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/BounceableInfo.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.panels.ui.compose
 
+import android.processor.immutability.Immutable
 import com.android.compose.animation.Bounceable
 import com.android.systemui.qs.panels.shared.model.SizedTile
 import com.android.systemui.qs.panels.ui.model.GridCell
@@ -23,6 +24,7 @@
 import com.android.systemui.qs.panels.ui.viewmodel.BounceableTileViewModel
 import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
 
+@Immutable
 data class BounceableInfo(
     val bounceable: BounceableTileViewModel,
     val previousTile: Bounceable?,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
index 2928ad1..8fda23d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
@@ -20,6 +20,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
@@ -67,17 +68,20 @@
             val it = sizedTiles[spanIndex]
             val column = cellIndex % columns
             cellIndex += it.width
-            Tile(
-                tile = it.tile,
-                iconOnly = it.isIcon,
-                modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
-                squishiness = { squishiness },
-                coroutineScope = scope,
-                bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
-                tileHapticsViewModelFactoryProvider = viewModel.tileHapticsViewModelFactoryProvider,
-                // There should be no QuickQuickSettings when the details view is enabled.
-                detailsViewModel = null,
-            )
+            key(it.tile.spec) {
+                Tile(
+                    tile = it.tile,
+                    iconOnly = it.isIcon,
+                    modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
+                    squishiness = { squishiness },
+                    coroutineScope = scope,
+                    bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+                    tileHapticsViewModelFactoryProvider =
+                        viewModel.tileHapticsViewModelFactoryProvider,
+                    // There should be no QuickQuickSettings when the details view is enabled.
+                    detailsViewModel = null,
+                )
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
index d72d5f1..85658bb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.panels.ui.compose.infinitegrid
 
+import android.content.Context
 import android.graphics.drawable.Animatable
 import android.graphics.drawable.AnimatedVectorDrawable
 import android.graphics.drawable.Drawable
@@ -83,7 +84,7 @@
 fun LargeTileContent(
     label: String,
     secondaryLabel: String?,
-    icon: Icon,
+    iconProvider: Context.() -> Icon,
     sideDrawable: Drawable?,
     colors: TileColors,
     squishiness: () -> Float,
@@ -129,7 +130,7 @@
                 }
         ) {
             SmallTileContent(
-                icon = icon,
+                iconProvider = iconProvider,
                 color = colors.icon,
                 size = { CommonTileDefaults.LargeTileIconSize },
                 modifier = Modifier.align(Alignment.Center),
@@ -194,14 +195,15 @@
 @Composable
 fun SmallTileContent(
     modifier: Modifier = Modifier,
-    icon: Icon,
+    iconProvider: Context.() -> Icon,
     color: Color,
     size: () -> Dp = { CommonTileDefaults.IconSize },
     animateToEnd: Boolean = false,
 ) {
+    val context = LocalContext.current
+    val icon = iconProvider(context)
     val animatedColor by animateColorAsState(color, label = "QSTileIconColor")
     val iconModifier = modifier.size({ size().roundToPx() }, { size().roundToPx() })
-    val context = LocalContext.current
     val loadedDrawable =
         remember(icon, context) {
             when (icon) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
index d975f10..d2ee126 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
@@ -19,7 +19,6 @@
 package com.android.systemui.qs.panels.ui.compose.infinitegrid
 
 import androidx.compose.animation.AnimatedContent
-import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.animateContentSize
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.animateDpAsState
@@ -76,6 +75,7 @@
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
@@ -460,29 +460,34 @@
             Modifier.fillMaxWidth().wrapContentHeight().testTag(AVAILABLE_TILES_GRID_TEST_TAG),
     ) {
         groupedTiles.forEach { (category, tiles) ->
-            Text(
-                text = category.label.load() ?: "",
-                fontSize = 20.sp,
-                color = labelColors.label,
-                modifier = Modifier.fillMaxWidth().padding(start = 16.dp, bottom = 8.dp, top = 8.dp),
-            )
-            tiles.chunked(columns).forEach { row ->
-                Row(
-                    horizontalArrangement = spacedBy(TileArrangementPadding),
-                    modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max),
-                ) {
-                    row.forEachIndexed { index, tileGridCell ->
-                        AvailableTileGridCell(
-                            cell = tileGridCell,
-                            index = index,
-                            dragAndDropState = dragAndDropState,
-                            selectionState = selectionState,
-                            modifier = Modifier.weight(1f).fillMaxHeight(),
-                        )
-                    }
+            key(category) {
+                Text(
+                    text = category.label.load() ?: "",
+                    fontSize = 20.sp,
+                    color = labelColors.label,
+                    modifier =
+                        Modifier.fillMaxWidth().padding(start = 16.dp, bottom = 8.dp, top = 8.dp),
+                )
+                tiles.chunked(columns).forEach { row ->
+                    Row(
+                        horizontalArrangement = spacedBy(TileArrangementPadding),
+                        modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Max),
+                    ) {
+                        row.forEachIndexed { index, tileGridCell ->
+                            key(tileGridCell.tile.tileSpec) {
+                                AvailableTileGridCell(
+                                    cell = tileGridCell,
+                                    index = index,
+                                    dragAndDropState = dragAndDropState,
+                                    selectionState = selectionState,
+                                    modifier = Modifier.weight(1f).fillMaxHeight(),
+                                )
+                            }
+                        }
 
-                    // Spacers for incomplete rows
-                    repeat(columns - row.size) { Spacer(modifier = Modifier.weight(1f)) }
+                        // Spacers for incomplete rows
+                        repeat(columns - row.size) { Spacer(modifier = Modifier.weight(1f)) }
+                    }
                 }
             }
         }
@@ -711,7 +716,7 @@
         ) {
             // Icon
             SmallTileContent(
-                icon = cell.tile.icon,
+                iconProvider = { cell.tile.icon },
                 color = colors.icon,
                 animateToEnd = true,
                 modifier = Modifier.align(Alignment.Center),
@@ -781,7 +786,7 @@
         // Icon
         Box(Modifier.size(ToggleTargetSize)) {
             SmallTileContent(
-                icon = tile.icon,
+                iconProvider = { tile.icon },
                 color = colors.icon,
                 animateToEnd = true,
                 size = { CommonTileDefaults.IconSize - iconSizeDiff * progress() },
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
index 8fd99a5..66961b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
@@ -19,6 +19,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
@@ -94,16 +95,18 @@
             val it = sizedTiles[spanIndex]
             val column = cellIndex % columns
             cellIndex += it.width
-            Tile(
-                tile = it.tile,
-                iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
-                modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
-                squishiness = { squishiness },
-                tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
-                coroutineScope = scope,
-                bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
-                detailsViewModel = detailsViewModel,
-            )
+            key(it.tile.spec) {
+                Tile(
+                    tile = it.tile,
+                    iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
+                    modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
+                    squishiness = { squishiness },
+                    tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
+                    coroutineScope = scope,
+                    bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+                    detailsViewModel = detailsViewModel,
+                )
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
index 13b3311..47238d1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
@@ -18,6 +18,7 @@
 
 package com.android.systemui.qs.panels.ui.compose.infinitegrid
 
+import android.content.Context
 import android.content.res.Resources
 import android.service.quicksettings.Tile.STATE_ACTIVE
 import android.service.quicksettings.Tile.STATE_INACTIVE
@@ -45,7 +46,10 @@
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.Alignment
@@ -65,7 +69,6 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.compose.animation.Expandable
 import com.android.compose.animation.bounceable
@@ -90,7 +93,6 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.ui.compose.borderOnFocus
 import com.android.systemui.res.R
-import java.util.function.Supplier
 import kotlinx.coroutines.CoroutineScope
 
 private const val TEST_TAG_SMALL = "qs_tile_small"
@@ -126,10 +128,19 @@
     modifier: Modifier = Modifier,
     detailsViewModel: DetailsViewModel?,
 ) {
-    val state: QSTile.State by tile.state.collectAsStateWithLifecycle(tile.currentState)
     val currentBounceableInfo by rememberUpdatedState(bounceableInfo)
     val resources = resources()
-    val uiState = remember(state, resources) { state.toUiState(resources) }
+
+    /*
+     * Use produce state because [QSTile.State] doesn't have well defined equals (due to
+     * inheritance). This way, even if tile.state changes, uiState may not change and lead to
+     * recomposition.
+     */
+    val uiState by
+        produceState(tile.currentState.toUiState(resources), tile, resources) {
+            tile.state.collect { value = it.toUiState(resources) }
+        }
+
     val colors = TileDefaults.getColorForState(uiState, iconOnly)
     val hapticsViewModel: TileHapticsViewModel? =
         rememberViewModel(traceName = "TileHapticsViewModel") {
@@ -137,7 +148,7 @@
         }
 
     // TODO(b/361789146): Draw the shapes instead of clipping
-    val tileShape = TileDefaults.animateTileShape(uiState.state)
+    val tileShape by TileDefaults.animateTileShapeAsState(uiState.state)
     val animatedColor by animateColorAsState(colors.background, label = "QSTileBackgroundColor")
 
     TileExpandable(
@@ -187,15 +198,15 @@
             uiState = uiState,
             iconOnly = iconOnly,
         ) {
-            val icon = getTileIcon(icon = uiState.icon)
+            val iconProvider: Context.() -> Icon = { getTileIcon(icon = uiState.icon) }
             if (iconOnly) {
                 SmallTileContent(
-                    icon = icon,
+                    iconProvider = iconProvider,
                     color = colors.icon,
                     modifier = Modifier.align(Alignment.Center),
                 )
             } else {
-                val iconShape = TileDefaults.animateIconShape(uiState.state)
+                val iconShape by TileDefaults.animateIconShapeAsState(uiState.state)
                 val secondaryClick: (() -> Unit)? =
                     {
                             hapticsViewModel?.setTileInteractionState(
@@ -207,7 +218,7 @@
                 LargeTileContent(
                     label = uiState.label,
                     secondaryLabel = uiState.secondaryLabel,
-                    icon = icon,
+                    iconProvider = iconProvider,
                     sideDrawable = uiState.sideDrawable,
                     colors = colors,
                     iconShape = iconShape,
@@ -269,7 +280,7 @@
 
     Box(
         modifier
-            .clip(TileDefaults.animateTileShape(state = uiState.state))
+            .clip(TileDefaults.animateTileShapeAsState(state = uiState.state).value)
             .background(colors.background)
             .height(TileHeight)
             .tilePadding()
@@ -277,7 +288,7 @@
         LargeTileContent(
             label = uiState.label,
             secondaryLabel = "",
-            icon = getTileIcon(icon = uiState.icon),
+            iconProvider = { getTileIcon(icon = uiState.icon) },
             sideDrawable = null,
             colors = colors,
             squishiness = { 1f },
@@ -285,14 +296,12 @@
     }
 }
 
-@Composable
-private fun getTileIcon(icon: Supplier<QSTile.Icon?>): Icon {
-    val context = LocalContext.current
-    return icon.get()?.let {
+private fun Context.getTileIcon(icon: QSTile.Icon?): Icon {
+    return icon?.let {
         if (it is QSTileImpl.ResourceIcon) {
             Icon.Resource(it.resId, null)
         } else {
-            Icon.Loaded(it.getDrawable(context), null)
+            Icon.Loaded(it.getDrawable(this), null)
         }
     } ?: Icon.Resource(R.drawable.ic_error_outline, null)
 }
@@ -348,6 +357,7 @@
 
     /** An active tile without dual target uses the active color as background */
     @Composable
+    @ReadOnlyComposable
     fun activeTileColors(): TileColors =
         TileColors(
             background = MaterialTheme.colorScheme.primary,
@@ -359,6 +369,7 @@
 
     /** An active tile with dual target only show the active color on the icon */
     @Composable
+    @ReadOnlyComposable
     fun activeDualTargetTileColors(): TileColors =
         TileColors(
             background = MaterialTheme.colorScheme.surfaceVariant,
@@ -369,6 +380,7 @@
         )
 
     @Composable
+    @ReadOnlyComposable
     fun inactiveDualTargetTileColors(): TileColors =
         TileColors(
             background = MaterialTheme.colorScheme.surfaceVariant,
@@ -379,6 +391,7 @@
         )
 
     @Composable
+    @ReadOnlyComposable
     fun inactiveTileColors(): TileColors =
         TileColors(
             background = MaterialTheme.colorScheme.surfaceVariant,
@@ -389,6 +402,7 @@
         )
 
     @Composable
+    @ReadOnlyComposable
     fun unavailableTileColors(): TileColors =
         TileColors(
             background = MaterialTheme.colorScheme.surface,
@@ -399,6 +413,7 @@
         )
 
     @Composable
+    @ReadOnlyComposable
     fun getColorForState(uiState: TileUiState, iconOnly: Boolean): TileColors {
         return when (uiState.state) {
             STATE_ACTIVE -> {
@@ -422,8 +437,8 @@
     }
 
     @Composable
-    fun animateIconShape(state: Int): RoundedCornerShape {
-        return animateShape(
+    fun animateIconShapeAsState(state: Int): State<RoundedCornerShape> {
+        return animateShapeAsState(
             state = state,
             activeCornerRadius = ActiveIconCornerRadius,
             label = "QSTileCornerRadius",
@@ -431,8 +446,8 @@
     }
 
     @Composable
-    fun animateTileShape(state: Int): RoundedCornerShape {
-        return animateShape(
+    fun animateTileShapeAsState(state: Int): State<RoundedCornerShape> {
+        return animateShapeAsState(
             state = state,
             activeCornerRadius = ActiveTileCornerRadius,
             label = "QSTileIconCornerRadius",
@@ -440,7 +455,11 @@
     }
 
     @Composable
-    fun animateShape(state: Int, activeCornerRadius: Dp, label: String): RoundedCornerShape {
+    fun animateShapeAsState(
+        state: Int,
+        activeCornerRadius: Dp,
+        label: String,
+    ): State<RoundedCornerShape> {
         val animatedCornerRadius by
             animateDpAsState(
                 targetValue =
@@ -459,7 +478,7 @@
                 }
             }
         }
-        return RoundedCornerShape(corner)
+        return remember { derivedStateOf { RoundedCornerShape(corner) } }
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
index 85db952..f3c06a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/EditModeButton.kt
@@ -54,7 +54,7 @@
         ) {
             Icon(
                 imageVector = Icons.Default.Edit,
-                contentDescription = stringResource(id = R.string.qs_edit),
+                contentDescription = stringResource(id = R.string.accessibility_quick_settings_edit),
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
index 37fa9e7..37b1642 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/toolbar/Toolbar.kt
@@ -18,12 +18,9 @@
 
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.requiredHeight
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.dp
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.lifecycle.rememberViewModel
 import com.android.systemui.qs.footer.ui.compose.IconButton
@@ -33,10 +30,7 @@
 fun Toolbar(toolbarViewModelFactory: ToolbarViewModel.Factory, modifier: Modifier = Modifier) {
     val viewModel = rememberViewModel("Toolbar") { toolbarViewModelFactory.create() }
 
-    Row(
-        modifier = modifier.fillMaxWidth().requiredHeight(48.dp),
-        verticalAlignment = Alignment.CenterVertically,
-    ) {
+    Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
         viewModel.userSwitcherViewModel?.let {
             IconButton(it, Modifier.sysuiResTag("multi_user_switch"))
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
index 2fc7f0f..19e542e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.qs.tileimpl.SubtitleArrayMapping
 import com.android.systemui.res.R
-import java.util.function.Supplier
 
 @Immutable
 data class TileUiState(
@@ -36,7 +35,7 @@
     val state: Int,
     val handlesLongClick: Boolean,
     val handlesSecondaryClick: Boolean,
-    val icon: Supplier<QSTile.Icon?>,
+    val icon: QSTile.Icon?,
     val sideDrawable: Drawable?,
     val accessibilityUiState: AccessibilityUiState,
 )
@@ -91,7 +90,7 @@
         state = if (disabledByPolicy) Tile.STATE_UNAVAILABLE else state,
         handlesLongClick = handlesLongClick,
         handlesSecondaryClick = handlesSecondaryClick,
-        icon = icon?.let { Supplier { icon } } ?: iconSupplier ?: Supplier { null },
+        icon = icon ?: iconSupplier?.get(),
         sideDrawable = sideViewCustomDrawable,
         AccessibilityUiState(
             contentDescription?.toString() ?: "",
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index ad027b4..30c2adf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -24,6 +24,7 @@
 import android.app.Dialog;
 import android.content.Intent;
 import android.media.MediaRouter.RouteInfo;
+import android.media.projection.StopReason;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
@@ -183,7 +184,7 @@
                 });
             }
         } else {
-            mController.stopCasting(activeDevices.get(0));
+            mController.stopCasting(activeDevices.get(0), StopReason.STOP_QS_TILE);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 42a0cb1..b7ff63c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -41,6 +41,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.res.R;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.DataSaverController;
 
@@ -56,6 +57,7 @@
     private final DataSaverController mDataSaverController;
     private final DialogTransitionAnimator mDialogTransitionAnimator;
     private final SystemUIDialog.Factory mSystemUIDialogFactory;
+    private final ShadeDialogContextInteractor mShadeDialogContextInteractor;
 
     @Inject
     public DataSaverTile(
@@ -70,13 +72,15 @@
             QSLogger qsLogger,
             DataSaverController dataSaverController,
             DialogTransitionAnimator dialogTransitionAnimator,
-            SystemUIDialog.Factory systemUIDialogFactory
+            SystemUIDialog.Factory systemUIDialogFactory,
+            ShadeDialogContextInteractor shadeDialogContextInteractor
     ) {
         super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
         mDataSaverController = dataSaverController;
         mDialogTransitionAnimator = dialogTransitionAnimator;
         mSystemUIDialogFactory = systemUIDialogFactory;
+        mShadeDialogContextInteractor = shadeDialogContextInteractor;
         mDataSaverController.observe(getLifecycle(), this);
     }
 
@@ -102,7 +106,8 @@
         // Show a dialog to confirm first. Dialogs shown by the DialogTransitionAnimator must be
         // created and shown on the main thread, so we post it to the UI handler.
         mUiHandler.post(() -> {
-            SystemUIDialog dialog = mSystemUIDialogFactory.create(mContext);
+            SystemUIDialog dialog = mSystemUIDialogFactory.create(
+                    mShadeDialogContextInteractor.getContext());
             dialog.setTitle(com.android.internal.R.string.data_saver_enable_title);
             dialog.setMessage(com.android.internal.R.string.data_saver_description);
             dialog.setPositiveButton(com.android.internal.R.string.data_saver_enable_button,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt
index 989fc0f..5ba1527 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt
@@ -22,6 +22,7 @@
 import android.service.quicksettings.Tile
 import com.android.internal.logging.MetricsLogger
 import com.android.systemui.animation.Expandable
+import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
@@ -92,7 +93,8 @@
 
         state?.apply {
             this.state = tileState.activationState.legacyState
-            icon = maybeLoadResourceIcon(tileState.iconRes ?: R.drawable.ic_qs_notes)
+            icon =
+                maybeLoadResourceIcon((tileState.icon as Icon.Loaded).res ?: R.drawable.ic_qs_notes)
             label = tileState.label
             contentDescription = tileState.contentDescription
             expandedAccessibilityClassName = tileState.expandedAccessibilityClassName
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 fc82592..ec8d30b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -18,6 +18,7 @@
 
 import android.app.Dialog;
 import android.content.Intent;
+import android.media.projection.StopReason;
 import android.os.Handler;
 import android.os.Looper;
 import android.service.quicksettings.Tile;
@@ -226,7 +227,7 @@
     }
 
     private void stopRecording() {
-        mController.stopRecording();
+        mController.stopRecording(StopReason.STOP_QS_TILE);
     }
 
     private final class Callback implements RecordingController.RecordingStateChangeCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index 19b45d5..7516ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -193,7 +193,7 @@
                 if (mJob == null) {
                     mJob = WifiUtils.checkWepAllowed(mContext, mCoroutineScope, wifiEntry.getSsid(),
                             WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, intent -> {
-                                mInternetDialogController.startActivity(intent, view);
+                                mInternetDialogController.startActivityForDialog(intent);
                                 return null;
                             }, () -> {
                                 wifiConnect(wifiEntry, view);
@@ -211,7 +211,7 @@
                         true /* connectForCaller */);
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
-                mContext.startActivity(intent);
+                mInternetDialogController.startActivityForDialog(intent);
                 return;
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index dbe1ae9..7036ef91 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -781,6 +781,10 @@
         mActivityStarter.postStartActivityDismissingKeyguard(intent, 0, controller);
     }
 
+    void startActivityForDialog(Intent intent) {
+        mActivityStarter.startActivity(intent, false /* dismissShade */);
+    }
+
     void launchNetworkSetting(View view) {
         startActivity(getSettingsIntent(), view);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
index 70c2a2a..5e9deec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
@@ -72,6 +72,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.res.R;
 import com.android.systemui.shade.ShadeDisplayAware;
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.wifitrackerlib.WifiEntry;
@@ -104,9 +105,9 @@
     private final Handler mHandler;
     private final Executor mBackgroundExecutor;
     private final DialogTransitionAnimator mDialogTransitionAnimator;
-    private final Context mContext;
     private final boolean mAboveStatusBar;
     private final SystemUIDialog.Factory mSystemUIDialogFactory;
+    private final ShadeDialogContextInteractor mShadeDialogContextInteractor;
 
     @VisibleForTesting
     protected InternetAdapter mAdapter;
@@ -204,10 +205,11 @@
             @Main Handler handler,
             @Background Executor executor,
             KeyguardStateController keyguardStateController,
-            SystemUIDialog.Factory systemUIDialogFactory) {
-        mContext = context;
+            SystemUIDialog.Factory systemUIDialogFactory,
+            ShadeDialogContextInteractor shadeDialogContextInteractor) {
         mAboveStatusBar = aboveStatusBar;
         mSystemUIDialogFactory = systemUIDialogFactory;
+        mShadeDialogContextInteractor = shadeDialogContextInteractor;
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialog");
         }
@@ -230,7 +232,8 @@
 
     @Override
     public SystemUIDialog createDialog() {
-        SystemUIDialog dialog = mSystemUIDialogFactory.create(this, mContext);
+        SystemUIDialog dialog = mSystemUIDialogFactory.create(this,
+                mShadeDialogContextInteractor.getContext());
         if (!mAboveStatusBar) {
             dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
index 34c2ec9..80d429c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/airplane/domain/AirplaneModeMapper.kt
@@ -35,13 +35,13 @@
 
     override fun map(config: QSTileConfig, data: AirplaneModeTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes =
+            val iconRes =
                 if (data.isEnabled) {
                     R.drawable.qs_airplane_icon_on
                 } else {
                     R.drawable.qs_airplane_icon_off
                 }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             if (data.isEnabled) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 secondaryLabel = resources.getStringArray(R.array.tile_states_airplane)[2]
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
index a72992d..d56d994 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/alarm/domain/AlarmTileMapper.kt
@@ -84,8 +84,8 @@
                     secondaryLabel = resources.getString(R.string.qs_alarm_tile_no_alarm)
                 }
             }
-            iconRes = R.drawable.ic_alarm
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = R.drawable.ic_alarm
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             sideViewIcon = QSTileState.SideViewIcon.Chevron
             contentDescription = label
             supportedActions = setOf(QSTileState.UserAction.CLICK)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
index e116d8c..72759c5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/battery/ui/BatterySaverTileMapper.kt
@@ -38,10 +38,10 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             label = resources.getString(R.string.battery_detail_switch_title)
             contentDescription = label
-            iconRes =
+            val iconRes =
                 if (data.isPowerSaving) R.drawable.qs_battery_saver_icon_on
                 else R.drawable.qs_battery_saver_icon_off
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             sideViewIcon = QSTileState.SideViewIcon.None
 
             if (data.isPluggedIn) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
index 21b9f65..e5a0fe8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/colorcorrection/domain/ColorCorrectionTileMapper.kt
@@ -37,8 +37,8 @@
     override fun map(config: QSTileConfig, data: ColorCorrectionTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
             val subtitleArray = resources.getStringArray(R.array.tile_states_color_correction)
-            iconRes = R.drawable.ic_qs_color_correction
-            icon = Icon.Loaded(resources.getDrawable(R.drawable.ic_qs_color_correction)!!, null)
+            val iconRes = R.drawable.ic_qs_color_correction
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             if (data.isEnabled) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 secondaryLabel = subtitleArray[2]
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
index 2dfb1fc..32ccba6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/flashlight/domain/FlashlightMapper.kt
@@ -35,14 +35,14 @@
 
     override fun map(config: QSTileConfig, data: FlashlightTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes =
+            val iconRes =
                 if (data is FlashlightTileModel.FlashlightAvailable && data.isEnabled) {
                     R.drawable.qs_flashlight_icon_on
                 } else {
                     R.drawable.qs_flashlight_icon_off
                 }
 
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
             contentDescription = label
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
index 7f41cbd..c571b13 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/fontscaling/domain/FontScalingTileMapper.kt
@@ -36,8 +36,8 @@
 
     override fun map(config: QSTileConfig, data: FontScalingTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes = R.drawable.ic_qs_font_scaling
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = R.drawable.ic_qs_font_scaling
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             contentDescription = label
             activationState = QSTileState.ActivationState.ACTIVE
             sideViewIcon = QSTileState.SideViewIcon.Chevron
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
index 4c302b3..12f7149 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/hearingdevices/domain/HearingDevicesTileMapper.kt
@@ -37,8 +37,8 @@
     override fun map(config: QSTileConfig, data: HearingDevicesTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
             label = resources.getString(R.string.quick_settings_hearing_devices_label)
-            iconRes = R.drawable.qs_hearing_devices_icon
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = R.drawable.qs_hearing_devices_icon
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             sideViewIcon = QSTileState.SideViewIcon.Chevron
             contentDescription = label
             if (data.isAnyActiveHearingDevice) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapper.kt
index 1a6876d..7ad01e4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/InternetTileMapper.kt
@@ -61,11 +61,11 @@
 
             when (val dataIcon = data.icon) {
                 is InternetTileIconModel.ResourceId -> {
-                    iconRes = dataIcon.resId
                     icon =
                         Icon.Loaded(
                             resources.getDrawable(dataIcon.resId, theme),
                             contentDescription = null,
+                            dataIcon.resId,
                         )
                 }
 
@@ -76,11 +76,11 @@
                 }
 
                 is InternetTileIconModel.Satellite -> {
-                    iconRes = dataIcon.resourceIcon.res // level is inferred from res
                     icon =
                         Icon.Loaded(
                             resources.getDrawable(dataIcon.resourceIcon.res, theme),
                             contentDescription = null,
+                            dataIcon.resourceIcon.res,
                         )
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
index 8d35b24..05590e8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/inversion/domain/ColorInversionTileMapper.kt
@@ -35,7 +35,7 @@
     override fun map(config: QSTileConfig, data: ColorInversionTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
             val subtitleArray = resources.getStringArray(R.array.tile_states_inversion)
-
+            val iconRes: Int
             if (data.isEnabled) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 secondaryLabel = subtitleArray[2]
@@ -45,7 +45,7 @@
                 secondaryLabel = subtitleArray[1]
                 iconRes = R.drawable.qs_invert_colors_icon_off
             }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             contentDescription = label
             supportedActions =
                 setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
index 3557c1a..afb137e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingMapper.kt
@@ -39,6 +39,7 @@
                     Icon.Loaded(
                         resources.getDrawable(R.drawable.qs_record_issue_icon_on, theme),
                         null,
+                        R.drawable.qs_record_issue_icon_on,
                     )
                 } else {
                     activationState = QSTileState.ActivationState.INACTIVE
@@ -46,6 +47,7 @@
                     Icon.Loaded(
                         resources.getDrawable(R.drawable.qs_record_issue_icon_off, theme),
                         null,
+                        R.drawable.qs_record_issue_icon_off,
                     )
                 }
             supportedActions = setOf(QSTileState.UserAction.CLICK)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
index dfc24a1..ced5a4f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/location/domain/LocationTileMapper.kt
@@ -35,13 +35,13 @@
 
     override fun map(config: QSTileConfig, data: LocationTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes =
+            val iconRes =
                 if (data.isEnabled) {
                     R.drawable.qs_location_icon_on
                 } else {
                     R.drawable.qs_location_icon_off
                 }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), contentDescription = null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
             label = resources.getString(R.string.quick_settings_location_label)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
index 9b2880b..479f618 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt
@@ -17,10 +17,10 @@
 package com.android.systemui.qs.tiles.impl.modes.domain.interactor
 
 import android.content.Context
+import android.graphics.drawable.Drawable
 import android.os.UserHandle
 import com.android.app.tracing.coroutines.flow.flowName
 import com.android.systemui.common.shared.model.Icon
-import com.android.systemui.common.shared.model.asIcon
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.modes.shared.ModesUi
 import com.android.systemui.modes.shared.ModesUiIcons
@@ -31,7 +31,6 @@
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
 import com.android.systemui.statusbar.policy.domain.model.ActiveZenModes
-import com.android.systemui.statusbar.policy.domain.model.ZenModeInfo
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.flow.Flow
@@ -68,37 +67,29 @@
     suspend fun getCurrentTileModel() = buildTileData(zenModeInteractor.getActiveModes())
 
     private fun buildTileData(activeModes: ActiveZenModes): ModesTileModel {
-        if (ModesUiIcons.isEnabled) {
-            val tileIcon = getTileIcon(activeModes.mainMode)
-            return ModesTileModel(
-                isActivated = activeModes.isAnyActive(),
-                icon = tileIcon.icon,
-                iconResId = tileIcon.resId,
-                activeModes = activeModes.modeNames,
-            )
-        } else {
-            return ModesTileModel(
-                isActivated = activeModes.isAnyActive(),
-                icon = context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(),
-                iconResId = ModesTile.ICON_RES_ID,
-                activeModes = activeModes.modeNames,
-            )
-        }
-    }
+        val drawable: Drawable
+        val iconRes: Int?
+        val activeMode = activeModes.mainMode
 
-    private data class TileIcon(val icon: Icon.Loaded, val resId: Int?)
-
-    private fun getTileIcon(activeMode: ZenModeInfo?): TileIcon {
-        return if (activeMode != null) {
+        if (ModesUiIcons.isEnabled && activeMode != null) {
             // ZenIconKey.resPackage is null if its resId is a system icon.
-            if (activeMode.icon.key.resPackage == null) {
-                TileIcon(activeMode.icon.drawable.asIcon(), activeMode.icon.key.resId)
-            } else {
-                TileIcon(activeMode.icon.drawable.asIcon(), null)
-            }
+            iconRes =
+                if (activeMode.icon.key.resPackage == null) {
+                    activeMode.icon.key.resId
+                } else {
+                    null
+                }
+            drawable = activeMode.icon.drawable
         } else {
-            TileIcon(context.getDrawable(ModesTile.ICON_RES_ID)!!.asIcon(), ModesTile.ICON_RES_ID)
+            iconRes = ModesTile.ICON_RES_ID
+            drawable = context.getDrawable(iconRes)!!
         }
+
+        return ModesTileModel(
+            isActivated = activeModes.isAnyActive(),
+            icon = Icon.Loaded(drawable, null, iconRes),
+            activeModes = activeModes.modeNames,
+        )
     }
 
     override fun availability(user: UserHandle): Flow<Boolean> = flowOf(ModesUi.isEnabled)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt
index db48123..d0eacbc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/model/ModesTileModel.kt
@@ -21,12 +21,10 @@
 data class ModesTileModel(
     val isActivated: Boolean,
     val activeModes: List<String>,
-    val icon: Icon.Loaded,
-
     /**
-     * Resource id corresponding to [icon]. Will only be present if it's know to correspond to a
-     * resource with a known id in SystemUI (such as resources from `android.R`,
-     * `com.android.internal.R`, or `com.android.systemui.res` itself).
+     * icon.res will only be present if it is known to correspond to a resource with a known id in
+     * SystemUI (such as resources from `android.R`, `com.android.internal.R`, or
+     * `com.android.systemui.res` itself).
      */
-    val iconResId: Int? = null
+    val icon: Icon.Loaded,
 )
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
index 1507ef4..99ae3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/ui/ModesTileMapper.kt
@@ -34,7 +34,6 @@
     QSTileDataToStateMapper<ModesTileModel> {
     override fun map(config: QSTileConfig, data: ModesTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes = data.iconResId
             icon = data.icon
             activationState =
                 if (data.isActivated) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
index 3569e4d..16b3628 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/night/ui/NightDisplayTileMapper.kt
@@ -49,7 +49,7 @@
             supportedActions =
                 setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
             sideViewIcon = QSTileState.SideViewIcon.None
-
+            val iconRes: Int
             if (data.isActivated) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 iconRes = R.drawable.qs_nightlight_icon_on
@@ -58,7 +58,7 @@
                 iconRes = R.drawable.qs_nightlight_icon_off
             }
 
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), contentDescription = null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
             secondaryLabel = getSecondaryLabel(data, resources)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
index a543619..ecdd711 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/notes/domain/NotesTileMapper.kt
@@ -35,8 +35,8 @@
 ) : QSTileDataToStateMapper<NotesTileModel> {
     override fun map(config: QSTileConfig, data: NotesTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
-            iconRes = R.drawable.ic_qs_notes
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), contentDescription = null)
+            val iconRes = R.drawable.ic_qs_notes
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             contentDescription = label
             activationState = QSTileState.ActivationState.INACTIVE
             sideViewIcon = QSTileState.SideViewIcon.Chevron
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
index 76f1e8b..5b3ea93 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/onehanded/ui/OneHandedModeTileMapper.kt
@@ -38,8 +38,8 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             val subtitleArray = resources.getStringArray(R.array.tile_states_onehanded)
             label = resources.getString(R.string.quick_settings_onehanded_label)
-            iconRes = com.android.internal.R.drawable.ic_qs_one_handed_mode
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = com.android.internal.R.drawable.ic_qs_one_handed_mode
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             if (data.isEnabled) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 secondaryLabel = subtitleArray[2]
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
index c546250..21e92d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/qr/ui/QRCodeScannerTileMapper.kt
@@ -38,8 +38,8 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             label = resources.getString(R.string.qr_code_scanner_title)
             contentDescription = label
-            iconRes = R.drawable.ic_qr_code_scanner
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = R.drawable.ic_qr_code_scanner
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             sideViewIcon = QSTileState.SideViewIcon.Chevron
             supportedActions = setOf(QSTileState.UserAction.CLICK)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
index 66d0f96..66759cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/reducebrightness/ui/ReduceBrightColorsTileMapper.kt
@@ -37,6 +37,7 @@
 
     override fun map(config: QSTileConfig, data: ReduceBrightColorsTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
+            val iconRes: Int
             if (data.isEnabled) {
                 activationState = QSTileState.ActivationState.ACTIVE
                 iconRes = R.drawable.qs_extra_dim_icon_on
@@ -50,7 +51,7 @@
                     resources
                         .getStringArray(R.array.tile_states_reduce_brightness)[Tile.STATE_INACTIVE]
             }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             label =
                 resources.getString(com.android.internal.R.string.reduce_bright_colors_feature_name)
             contentDescription = label
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
index a014422..000c702 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/rotation/ui/mapper/RotationLockTileMapper.kt
@@ -42,7 +42,7 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             label = resources.getString(R.string.quick_settings_rotation_unlocked_label)
             contentDescription = resources.getString(R.string.accessibility_quick_settings_rotation)
-
+            val iconRes: Int
             if (data.isRotationLocked) {
                 activationState = QSTileState.ActivationState.INACTIVE
                 secondaryLabel = EMPTY_SECONDARY_STRING
@@ -57,7 +57,7 @@
                     }
                 iconRes = R.drawable.qs_auto_rotate_icon_on
             }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             if (isDeviceFoldable(resources, deviceStateManager)) {
                 secondaryLabel = getSecondaryLabelWithPosture(activationState)
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
index aea4967..1d5cf29 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/saver/domain/DataSaverTileMapper.kt
@@ -36,6 +36,7 @@
     override fun map(config: QSTileConfig, data: DataSaverTileModel): QSTileState =
         QSTileState.build(resources, theme, config.uiConfig) {
             with(data) {
+                val iconRes: Int
                 if (isEnabled) {
                     activationState = QSTileState.ActivationState.ACTIVE
                     iconRes = R.drawable.qs_data_saver_icon_on
@@ -45,7 +46,7 @@
                     iconRes = R.drawable.qs_data_saver_icon_off
                     secondaryLabel = resources.getStringArray(R.array.tile_states_saver)[1]
                 }
-                icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+                icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
                 contentDescription = label
                 supportedActions =
                     setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
index 85aa674..9453447 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/interactor/ScreenRecordTileUserActionInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles.impl.screenrecord.domain.interactor
 
+import android.media.projection.StopReason
 import android.util.Log
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.systemui.animation.DialogCuj
@@ -61,7 +62,9 @@
                             Log.d(TAG, "Cancelling countdown")
                             withContext(backgroundContext) { recordingController.cancelCountdown() }
                         }
-                        is ScreenRecordModel.Recording -> screenRecordRepository.stopRecording()
+                        is ScreenRecordModel.Recording -> {
+                            screenRecordRepository.stopRecording(StopReason.STOP_QS_TILE)
+                        }
                         is ScreenRecordModel.DoingNothing ->
                             withContext(mainContext) {
                                 showPrompt(action.expandable, user.identifier)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
index f3136e0..0a61e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt
@@ -38,7 +38,7 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             label = resources.getString(R.string.quick_settings_screen_record_label)
             supportedActions = setOf(QSTileState.UserAction.CLICK)
-
+            val iconRes: Int
             when (data) {
                 is ScreenRecordModel.Recording -> {
                     activationState = QSTileState.ActivationState.ACTIVE
@@ -61,7 +61,7 @@
                         resources.getString(R.string.quick_settings_screen_record_start)
                 }
             }
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
             contentDescription =
                 if (TextUtils.isEmpty(secondaryLabel)) label
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
index 73e61b7..f54f46c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/sensorprivacy/ui/SensorPrivacyToggleTileMapper.kt
@@ -50,8 +50,8 @@
             contentDescription = label
             supportedActions =
                 setOf(QSTileState.UserAction.CLICK, QSTileState.UserAction.LONG_CLICK)
-            iconRes = sensorPrivacyTileResources.getIconRes(data.isBlocked)
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+            val iconRes = sensorPrivacyTileResources.getIconRes(data.isBlocked)
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
             sideViewIcon = QSTileState.SideViewIcon.None
 
             if (data.isBlocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
index e9aa46c..5933d65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/uimodenight/domain/UiModeNightTileMapper.kt
@@ -116,11 +116,11 @@
                     }
                 }
 
-                iconRes =
+                val iconRes =
                     if (activationState == QSTileState.ActivationState.ACTIVE)
                         R.drawable.qs_light_dark_theme_icon_on
                     else R.drawable.qs_light_dark_theme_icon_off
-                icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), null)
+                icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
                 supportedActions =
                     if (activationState == QSTileState.ActivationState.UNAVAILABLE)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
index 6a3195a..5b462ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/work/ui/WorkModeTileMapper.kt
@@ -41,8 +41,8 @@
         QSTileState.build(resources, theme, config.uiConfig) {
             label = getTileLabel()!!
             contentDescription = label
-            iconRes = com.android.internal.R.drawable.stat_sys_managed_profile_status
-            icon = Icon.Loaded(resources.getDrawable(iconRes!!, theme), contentDescription = null)
+            val iconRes = com.android.internal.R.drawable.stat_sys_managed_profile_status
+            icon = Icon.Loaded(resources.getDrawable(iconRes, theme), null, iconRes)
 
             when (data) {
                 is WorkModeTileModel.HasActiveProfile -> {
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 8394be5..c6af729 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
@@ -36,7 +36,6 @@
  */
 data class QSTileState(
     val icon: Icon?,
-    val iconRes: Int?,
     val label: CharSequence,
     val activationState: ActivationState,
     val secondaryLabel: CharSequence?,
@@ -58,7 +57,7 @@
         ): QSTileState {
             val iconDrawable = resources.getDrawable(config.iconRes, theme)
             return build(
-                Icon.Loaded(iconDrawable, null),
+                Icon.Loaded(iconDrawable, null, config.iconRes),
                 resources.getString(config.labelRes),
                 builder,
             )
@@ -115,7 +114,6 @@
     }
 
     class Builder(var icon: Icon?, var label: CharSequence) {
-        var iconRes: Int? = null
         var activationState: ActivationState = ActivationState.INACTIVE
         var secondaryLabel: CharSequence? = null
         var supportedActions: Set<UserAction> = setOf(UserAction.CLICK)
@@ -128,7 +126,6 @@
         fun build(): QSTileState =
             QSTileState(
                 icon,
-                iconRes,
                 label,
                 activationState,
                 secondaryLabel,
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 632eeef..c34edc8 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
@@ -260,8 +260,8 @@
                 icon =
                     when (val stateIcon = viewModelState.icon) {
                         is Icon.Loaded ->
-                            if (viewModelState.iconRes == null) DrawableIcon(stateIcon.drawable)
-                            else DrawableIconWithRes(stateIcon.drawable, viewModelState.iconRes)
+                            if (stateIcon.res == null) DrawableIcon(stateIcon.drawable)
+                            else DrawableIconWithRes(stateIcon.drawable, stateIcon.res)
                         is Icon.Resource -> ResourceIcon.get(stateIcon.res)
                         null -> null
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
index 8c54ab40..862dba1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.qs.user
 
 import android.app.Dialog
-import android.content.Context
 import android.content.DialogInterface
 import android.content.DialogInterface.BUTTON_NEUTRAL
 import android.content.Intent
@@ -34,6 +33,7 @@
 import com.android.systemui.qs.QSUserSwitcherEvent
 import com.android.systemui.qs.tiles.UserDetailView
 import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.user.ui.dialog.DialogShowerImpl
 import javax.inject.Inject
@@ -50,6 +50,7 @@
     private val dialogTransitionAnimator: DialogTransitionAnimator,
     private val uiEventLogger: UiEventLogger,
     private val dialogFactory: SystemUIDialog.Factory,
+    private val shadeDialogContextInteractor: ShadeDialogContextInteractor,
 ) {
 
     companion object {
@@ -63,7 +64,8 @@
      * Populate the dialog with information from and adapter obtained from
      * [userDetailViewAdapterProvider] and show it as launched from [expandable].
      */
-    fun showDialog(context: Context, expandable: Expandable) {
+    fun showDialog(expandable: Expandable) {
+        val context = shadeDialogContextInteractor.context
         with(dialogFactory.create(context)) {
             setShowForAllUsers(true)
             setCanceledOnTouchOutside(true)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
index 33bffc2..dc0c4dc 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlag.kt
@@ -23,7 +23,6 @@
 import com.android.systemui.flags.FlagToken
 import com.android.systemui.flags.RefactorFlagUtils
 import com.android.systemui.keyguard.KeyguardWmStateRefactor
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun
 import com.android.systemui.statusbar.phone.PredictiveBackSysUiFlag
 
@@ -37,7 +36,6 @@
         get() =
             sceneContainer() && // mainAconfigFlag
                 KeyguardWmStateRefactor.isEnabled &&
-                MigrateClocksToBlueprint.isEnabled &&
                 NotificationThrottleHun.isEnabled &&
                 PredictiveBackSysUiFlag.isEnabled
 
@@ -50,7 +48,6 @@
     inline fun getSecondaryFlags(): Sequence<FlagToken> =
         sequenceOf(
             KeyguardWmStateRefactor.token,
-            MigrateClocksToBlueprint.token,
             NotificationThrottleHun.token,
             PredictiveBackSysUiFlag.token,
             // NOTE: Changes should also be made in isEnabled and @EnableSceneContainer
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
index d7463f8..9ee99e4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.projection.StopReason;
 import android.os.Bundle;
 import android.os.CountDownTimer;
 import android.os.Process;
@@ -58,6 +59,7 @@
     private boolean mIsStarting;
     private boolean mIsRecording;
     private PendingIntent mStopIntent;
+    private @StopReason int mStopReason = StopReason.STOP_UNKNOWN;
     private final Bundle mInteractiveBroadcastOption;
     private CountDownTimer mCountDownTimer = null;
     private final Executor mMainExecutor;
@@ -83,7 +85,7 @@
             new UserTracker.Callback() {
                 @Override
                 public void onUserChanged(int newUser, @NonNull Context userContext) {
-                    stopRecording();
+                    stopRecording(StopReason.STOP_USER_SWITCH);
                 }
             };
 
@@ -240,9 +242,11 @@
     }
 
     /**
-     * Stop the recording
+     * Stop the recording and sets the stop reason to be used by the RecordingService
+     * @param stopReason the method of the recording stopped (i.e. QS tile, status bar chip, etc.)
      */
-    public void stopRecording() {
+    public void stopRecording(@StopReason int stopReason) {
+        mStopReason = stopReason;
         try {
             if (mStopIntent != null) {
                 mRecordingControllerLogger.logRecordingStopped();
@@ -277,6 +281,10 @@
         }
     }
 
+    public @StopReason int getStopReason() {
+        return mStopReason;
+    }
+
     @Override
     public void addCallback(@NonNull RecordingStateChangeCallback listener) {
         mListeners.add(listener);
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 8c207d1..f7b5271 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.media.MediaRecorder;
+import android.media.projection.StopReason;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -78,6 +79,7 @@
     private static final String EXTRA_SHOW_TAPS = "extra_showTaps";
     private static final String EXTRA_CAPTURE_TARGET = "extra_captureTarget";
     private static final String EXTRA_DISPLAY_ID = "extra_displayId";
+    private static final String EXTRA_STOP_REASON = "extra_stopReason";
 
     protected static final String ACTION_START = "com.android.systemui.screenrecord.START";
     protected static final String ACTION_SHOW_START_NOTIF =
@@ -242,7 +244,8 @@
                 // Check user ID - we may be getting a stop intent after user switch, in which case
                 // we want to post the notifications for that user, which is NOT current user
                 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_ID_NOT_SPECIFIED);
-                stopService(userId);
+                int stopReason = intent.getIntExtra(EXTRA_STOP_REASON, mController.getStopReason());
+                stopService(userId, stopReason);
                 break;
 
             case ACTION_SHARE:
@@ -486,11 +489,11 @@
                 getTag(), notificationIdForGroup, groupNotif, currentUser);
     }
 
-    private void stopService() {
-        stopService(USER_ID_NOT_SPECIFIED);
+    private void stopService(@StopReason int stopReason) {
+        stopService(USER_ID_NOT_SPECIFIED, stopReason);
     }
 
-    private void stopService(int userId) {
+    private void stopService(int userId, @StopReason int stopReason) {
         if (userId == USER_ID_NOT_SPECIFIED) {
             userId = mUserContextTracker.getUserContext().getUserId();
         }
@@ -499,7 +502,7 @@
         setTapsVisible(mOriginalShowTaps);
         try {
             if (getRecorder() != null) {
-                getRecorder().end();
+                getRecorder().end(stopReason);
             }
             saveRecording(userId);
         } catch (RuntimeException exception) {
@@ -598,7 +601,8 @@
      * @return
      */
     protected Intent getNotificationIntent(Context context) {
-        return new Intent(context, this.getClass()).setAction(ACTION_STOP_NOTIF);
+        return new Intent(context, this.getClass()).setAction(ACTION_STOP_NOTIF)
+                .putExtra(EXTRA_STOP_REASON, StopReason.STOP_HOST_APP);
     }
 
     private Intent getShareIntent(Context context, Uri path) {
@@ -610,14 +614,17 @@
     @Override
     public void onInfo(MediaRecorder mr, int what, int extra) {
         Log.d(getTag(), "Media recorder info: " + what);
-        onStartCommand(getStopIntent(this), 0, 0);
+        // Stop due to record reaching size limits so log as stopping due to error
+        Intent stopIntent = getStopIntent(this);
+        stopIntent.putExtra(EXTRA_STOP_REASON, StopReason.STOP_ERROR);
+        onStartCommand(stopIntent, 0, 0);
     }
 
     @Override
-    public void onStopped() {
+    public void onStopped(@StopReason int stopReason) {
         if (mController.isRecording()) {
             Log.d(getTag(), "Stopping recording because the system requested the stop");
-            stopService();
+            stopService(stopReason);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
index 2ca0621..f4455bf 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
@@ -41,6 +41,7 @@
 import android.media.projection.IMediaProjectionManager;
 import android.media.projection.MediaProjection;
 import android.media.projection.MediaProjectionManager;
+import android.media.projection.StopReason;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
@@ -300,7 +301,7 @@
     /**
      * End screen recording, throws an exception if stopping recording failed
      */
-    void end() throws IOException {
+    void end(@StopReason int stopReason) throws IOException {
         Closer closer = new Closer();
 
         // MediaRecorder might throw RuntimeException if stopped immediately after starting
@@ -309,7 +310,17 @@
         closer.register(mMediaRecorder::release);
         closer.register(mInputSurface::release);
         closer.register(mVirtualDisplay::release);
-        closer.register(mMediaProjection::stop);
+        closer.register(() -> {
+            if (stopReason == StopReason.STOP_UNKNOWN) {
+                // Attempt to call MediaProjection#stop() even if it might have already been called.
+                // If projection has already been stopped, then nothing will happen. Else, stop
+                // will be logged as a manually requested stop from host app.
+                mMediaProjection.stop();
+            } else {
+                // In any other case, the stop reason is related to the recorder, so pass it on here
+                mMediaProjection.stop(stopReason);
+            }
+        });
         closer.register(this::stopInternalAudioRecording);
 
         closer.close();
@@ -323,7 +334,7 @@
     @Override
     public void onStop() {
         Log.d(TAG, "The system notified about stopping the projection");
-        mListener.onStopped();
+        mListener.onStopped(StopReason.STOP_UNKNOWN);
     }
 
     private void stopInternalAudioRecording() {
@@ -453,7 +464,7 @@
          * For example, this might happen when doing partial screen sharing of an app
          * and the app that is being captured is closed.
          */
-        void onStopped();
+        void onStopped(@StopReason int stopReason);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
index 91c6b47..88f373e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt
@@ -70,6 +70,7 @@
     }
 
     companion object {
+
         private val RECORDABLE_DISPLAY_TYPES =
             intArrayOf(
                 Display.TYPE_OVERLAY,
@@ -83,8 +84,10 @@
                 .mediaProjectionConnectedDisplayNoVirtualDevice()
 
         fun createOptionList(displayManager: DisplayManager): List<ScreenShareOption> {
-            if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
-                return listOf(
+            val connectedDisplays = getConnectedDisplays(displayManager)
+
+            val options =
+                mutableListOf(
                     ScreenShareOption(
                         SINGLE_APP,
                         R.string.screenrecord_permission_dialog_option_text_single_app,
@@ -103,33 +106,10 @@
                         displayName = Build.MODEL,
                     ),
                 )
-            }
 
-            return listOf(
-                ScreenShareOption(
-                    SINGLE_APP,
-                    R.string.screenrecord_permission_dialog_option_text_single_app,
-                    R.string.screenrecord_permission_dialog_warning_single_app,
-                    startButtonText =
-                        R.string
-                            .media_projection_entry_generic_permission_dialog_continue_single_app,
-                ),
-                ScreenShareOption(
-                    ENTIRE_SCREEN,
-                    R.string.screenrecord_permission_dialog_option_text_entire_screen_for_display,
-                    R.string.screenrecord_permission_dialog_warning_entire_screen,
-                    startButtonText =
-                        R.string.screenrecord_permission_dialog_continue_entire_screen,
-                    displayId = Display.DEFAULT_DISPLAY,
-                    displayName = Build.MODEL,
-                ),
-            ) +
-                displayManager.displays
-                    .filter {
-                        it.displayId != Display.DEFAULT_DISPLAY &&
-                            (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
-                    }
-                    .map {
+            if (connectedDisplays.isNotEmpty()) {
+                options +=
+                    connectedDisplays.map {
                         ScreenShareOption(
                             ENTIRE_SCREEN,
                             R.string
@@ -144,6 +124,18 @@
                             displayName = it.name,
                         )
                     }
+            }
+            return options.toList()
+        }
+
+        private fun getConnectedDisplays(displayManager: DisplayManager): List<Display> {
+            if (!com.android.media.projection.flags.Flags.mediaProjectionConnectedDisplay()) {
+                return emptyList()
+            }
+            return displayManager.displays.filter {
+                it.displayId != Display.DEFAULT_DISPLAY &&
+                    (!filterDeviceTypeFlag || it.type in RECORDABLE_DISPLAY_TYPES)
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepository.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepository.kt
index 9eeb3b9..b6b8ffa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/data/repository/ScreenRecordRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenrecord.data.repository
 
+import android.media.projection.StopReason
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.screenrecord.RecordingController
@@ -41,7 +42,7 @@
     val screenRecordState: Flow<ScreenRecordModel>
 
     /** Stops the recording. */
-    suspend fun stopRecording()
+    suspend fun stopRecording(@StopReason stopReason: Int)
 }
 
 @SysUISingleton
@@ -95,7 +96,7 @@
         }
     }
 
-    override suspend fun stopRecording() {
-        withContext(bgCoroutineContext) { recordingController.stopRecording() }
+    override suspend fun stopRecording(@StopReason stopReason: Int) {
+        withContext(bgCoroutineContext) { recordingController.stopRecording(stopReason) }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
index a7b51faa..10ac2cf 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.scrim;
 
+import static com.android.systemui.Flags.notificationShadeBlur;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -214,8 +216,7 @@
     public void draw(@NonNull Canvas canvas) {
         mPaint.setColor(mMainColor);
         mPaint.setAlpha(mAlpha);
-        if (WindowBlurFlag.isEnabled()) {
-            // TODO(b/370555223): Match the alpha to the visual spec when it is finalized.
+        if (notificationShadeBlur() || WindowBlurFlag.isEnabled()) {
             // TODO (b/381263600), wire this at ScrimController, move it to PrimaryBouncerTransition
             mPaint.setAlpha((int) (0.5f * mAlpha));
         }
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index 4bfa61e..0f80e74 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.scrim;
 
+import static com.android.systemui.Flags.notificationShadeBlur;
+
 import static java.lang.Float.isNaN;
 
 import android.annotation.NonNull;
@@ -39,13 +41,12 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.res.R;
 import com.android.systemui.shade.TouchLogger;
 import com.android.systemui.util.LargeScreenUtils;
 
 import java.util.concurrent.Executor;
 
-import static com.android.systemui.Flags.notificationShadeBlur;
-
 /**
  * A view which can draw a scrim.  This view maybe be used in multiple windows running on different
  * threads, but is controlled by {@link com.android.systemui.statusbar.phone.ScrimController} so we
@@ -253,8 +254,11 @@
                 mainTinted = ColorUtils.blendARGB(mColors.getMainColor(), mTintColor, tintAmount);
             }
             if (notificationShadeBlur()) {
-                // TODO(b/370555223): Fix color and transparency to match visual spec exactly
-                mainTinted = ColorUtils.blendARGB(mColors.getMainColor(), Color.GRAY, 0.5f);
+                int layerAbove = ColorUtils.setAlphaComponent(
+                        getResources().getColor(R.color.shade_panel, null),
+                        (int) (0.4f * 255));
+                int layerBelow = ColorUtils.setAlphaComponent(Color.WHITE, (int) (0.1f * 255));
+                mainTinted = ColorUtils.compositeColors(layerAbove, layerBelow);
             }
             drawable.setColor(mainTinted, animated);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
index 60ed2de..b0cbc06 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/DisplayTrackerImpl.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.settings
 
 import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS
 import android.os.Handler
 import android.view.Display
 import androidx.annotation.GuardedBy
@@ -104,7 +104,7 @@
                     displayBrightnessChangedListener,
                     backgroundHandler,
                     /* eventFlags */ 0,
-                    PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS,
+                    PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS,
                 )
             }
             brightnessCallbacks.add(DisplayTrackerDataItem(WeakReference(callback), executor))
diff --git a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
index d78f4d8..2ca7647 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/DebugDrawable.java
@@ -85,22 +85,6 @@
                             mNotificationPanelViewController.getExpandedFraction()),
                     Color.MAGENTA, "calculateNotificationsTopPadding()");
         }
-        drawDebugInfo(canvas, mNotificationPanelViewController.getClockPositionResult().clockY,
-                Color.GRAY, "mClockPositionResult.clockY");
-
-        if (mNotificationPanelViewController.isKeyguardShowing()) {
-            // Notifications have the space between those two lines.
-            drawDebugInfo(canvas,
-                    mNotificationStackScrollLayoutController.getTop()
-                            + (int) mNotificationPanelViewController
-                            .getKeyguardNotificationTopPadding(),
-                    Color.RED, "NSSL.getTop() + mKeyguardNotificationTopPadding");
-
-            drawDebugInfo(canvas, mNotificationStackScrollLayoutController.getBottom()
-                            - (int) mNotificationPanelViewController
-                            .getKeyguardNotificationBottomPadding(),
-                    Color.RED, "NSSL.getBottom() - mKeyguardNotificationBottomPadding");
-        }
 
         mDebugPaint.setColor(Color.CYAN);
         canvas.drawLine(0,
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index 61ac1a02..a379ef7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -67,6 +67,7 @@
 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
 import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
+import com.android.systemui.util.kotlin.Quad
 import com.android.systemui.util.kotlin.collectFlow
 import java.util.function.Consumer
 import javax.inject.Inject
@@ -409,11 +410,12 @@
                 shadeInteractor.isAnyFullyExpanded,
                 shadeInteractor.isUserInteracting,
                 shadeInteractor.isShadeFullyCollapsed,
-                ::Triple,
+                shadeInteractor.isQsExpanded,
+                ::Quad,
             ),
-            { (isFullyExpanded, isUserInteracting, isShadeFullyCollapsed) ->
+            { (isFullyExpanded, isUserInteracting, isShadeFullyCollapsed, isQsExpanded) ->
                 shadeConsumingTouches = isUserInteracting
-                shadeShowing = !isShadeFullyCollapsed
+                shadeShowing = isQsExpanded || !isShadeFullyCollapsed
                 val expandedAndNotInteractive = isFullyExpanded && !isUserInteracting
 
                 // If we ever are fully expanded and not interacting, capture this state as we
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 9e88583..e168025 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -19,10 +19,7 @@
 import static android.view.View.INVISIBLE;
 import static android.view.View.VISIBLE;
 
-import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
 import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.keyguard.KeyguardClockSwitch.LARGE;
-import static com.android.keyguard.KeyguardClockSwitch.SMALL;
 import static com.android.systemui.Flags.msdlFeedback;
 import static com.android.systemui.Flags.predictiveBackAnimateShade;
 import static com.android.systemui.classifier.Classifier.BOUNCER_UNLOCK;
@@ -30,11 +27,7 @@
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 import static com.android.systemui.classifier.Classifier.UNLOCK;
 import static com.android.systemui.keyguard.shared.model.KeyguardState.AOD;
-import static com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING;
-import static com.android.systemui.keyguard.shared.model.KeyguardState.GONE;
 import static com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN;
-import static com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED;
-import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll;
 import static com.android.systemui.navigationbar.gestural.Utilities.isTrackpadThreeFingerSwipe;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_CLOSED;
 import static com.android.systemui.shade.ShadeExpansionStateManagerKt.STATE_OPEN;
@@ -58,7 +51,6 @@
 import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.Insets;
 import android.graphics.Rect;
@@ -69,18 +61,17 @@
 import android.os.Handler;
 import android.os.Trace;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.MathUtils;
 import android.view.HapticFeedbackConstants;
+import android.view.InputDevice;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
@@ -89,9 +80,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
-
-import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
@@ -101,21 +89,13 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.ActiveUnlockConfig;
-import com.android.keyguard.KeyguardClockSwitch.ClockSize;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
 import com.android.keyguard.KeyguardUnfoldTransition;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.Gefingerpoken;
-import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dagger.SysUISingleton;
@@ -129,24 +109,17 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.KeyguardViewConfigurator;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver;
+import com.android.systemui.keyguard.shared.model.ClockSize;
 import com.android.systemui.keyguard.shared.model.Edge;
 import com.android.systemui.keyguard.shared.model.TransitionState;
 import com.android.systemui.keyguard.shared.model.TransitionStep;
 import com.android.systemui.keyguard.ui.binder.KeyguardLongPressViewBinder;
-import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardTouchHandlingViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
 import com.android.systemui.media.controls.ui.controller.KeyguardMediaController;
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
@@ -165,7 +138,6 @@
 import com.android.systemui.qs.flags.QSComposeFragment;
 import com.android.systemui.res.R;
 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
-import com.android.systemui.scene.shared.model.Scenes;
 import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor;
 import com.android.systemui.shade.data.repository.FlingInfo;
 import com.android.systemui.shade.data.repository.ShadeRepository;
@@ -221,10 +193,7 @@
 import com.android.systemui.statusbar.phone.TapAgainViewController;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
 import com.android.systemui.statusbar.policy.SplitShadeStateController;
 import com.android.systemui.unfold.SysUIUnfoldComponent;
 import com.android.systemui.util.Compile;
@@ -258,7 +227,6 @@
 
     public static final String TAG = NotificationPanelView.class.getSimpleName();
     private static final boolean DEBUG_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
-    private static final boolean SPEW_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE);
     private static final boolean DEBUG_DRAWABLE = false;
     /** The parallax amount of the quick settings translation when dragging down the panel. */
     public static final float QS_PARALLAX_AMOUNT = 0.175f;
@@ -309,7 +277,6 @@
     private final ShadeHeadsUpChangedListener mOnHeadsUpChangedListener =
             new ShadeHeadsUpChangedListener();
     private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
-    private final SettingsChangeObserver mSettingsChangeObserver;
     private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
     private final NotificationPanelView mView;
     private final VibratorHelper mVibratorHelper;
@@ -327,12 +294,8 @@
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
     private final ConversationNotificationManager mConversationNotificationManager;
-    private final AuthController mAuthController;
     private final MediaHierarchyManager mMediaHierarchyManager;
     private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
-    private final KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
-    private final KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
     private final KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
     private final FragmentService mFragmentService;
     private final IStatusBarService mStatusBarService;
@@ -372,19 +335,7 @@
     private float mCurrentBackProgress = 0.0f;
     private boolean mExpanding;
     private boolean mSplitShadeEnabled;
-    /** The bottom padding reserved for elements of the keyguard measuring notifications. */
-    private float mKeyguardNotificationBottomPadding;
-    /**
-     * The top padding from where notification should start in lockscreen.
-     * Should be static also during animations and should match the Y of the first notification.
-     */
-    private float mKeyguardNotificationTopPadding;
-    /** Current max allowed keyguard notifications determined by measuring the panel. */
-    private int mMaxAllowedKeyguardNotifications;
-    private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
-    private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
     private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
-    private KeyguardStatusViewController mKeyguardStatusViewController;
     private NotificationsQuickSettingsContainer mNotificationContainerParent;
     private final NotificationsQSContainerController mNotificationsQSContainerController;
     private boolean mAnimateNextPositionUpdate;
@@ -394,8 +345,6 @@
     private OpenCloseListener mOpenCloseListener;
     private GestureRecorder mGestureRecorder;
 
-    private boolean mKeyguardQsUserSwitchEnabled;
-    private boolean mKeyguardUserSwitcherEnabled;
     private boolean mDozing;
     private boolean mDozingOnDown;
     private boolean mBouncerShowing;
@@ -406,7 +355,6 @@
     private float mOverStretchAmount;
     private float mDownX;
     private float mDownY;
-    private boolean mIsTrackpadReverseScroll;
     private int mDisplayTopInset = 0; // in pixels
     private int mDisplayRightInset = 0; // in pixels
     private int mDisplayLeftInset = 0; // in pixels
@@ -444,8 +392,6 @@
     Set<Animator> mTestSetOfAnimatorsUsed;
 
     private boolean mShowIconsWhenExpanded;
-    private int mIndicationBottomPadding;
-    private int mAmbientIndicationBottomPadding;
     /** Whether the notifications are displayed full width (no margins on the side). */
     private boolean mIsFullWidth;
     private boolean mBlockingExpansionForCurrentTouch;
@@ -471,8 +417,6 @@
 
     private int mPanelAlpha;
     private Runnable mPanelAlphaEndAction;
-    private float mBottomAreaShadeAlpha;
-    final ValueAnimator mBottomAreaShadeAlphaAnimator;
     private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
             (view, alpha) -> {
                 setAlphaInternal(alpha);
@@ -514,11 +458,6 @@
     /** Whether a collapse that started on the panel should allow the panel to intercept. */
     private boolean mIsPanelCollapseOnQQS;
 
-    /** Alpha of the views which only show on the keyguard but not in shade / shade locked. */
-    private float mKeyguardOnlyContentAlpha = 1.0f;
-    /** Y translation of the views that only show on the keyguard but in shade / shade locked. */
-    private int mKeyguardOnlyTransitionTranslationY = 0;
-    private float mUdfpsMaxYBurnInOffset;
     /** Are we currently in gesture navigation. */
     private boolean mIsGestureNavigation;
     private int mOldLayoutDirection;
@@ -584,31 +523,14 @@
     private boolean mIgnoreXTouchSlop;
     private boolean mExpandLatencyTracking;
     private boolean mUseExternalTouch = false;
-
-    /**
-     * Whether we're waking up and will play the delayed doze animation in
-     * {@link NotificationWakeUpCoordinator}. If so, we'll want to keep the clock centered until the
-     * delayed doze animation starts.
-     */
-    private boolean mWillPlayDelayedDozeAmountAnimation = false;
     private final DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
-    private final OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
-    private final LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
-    private final GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-    private final LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
-    private final PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
     private final SharedNotificationContainerInteractor mSharedNotificationContainerInteractor;
     private final ActiveNotificationsInteractor mActiveNotificationsInteractor;
     private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
     private final KeyguardInteractor mKeyguardInteractor;
     private final PowerInteractor mPowerInteractor;
-    private final KeyguardViewConfigurator mKeyguardViewConfigurator;
     private final CoroutineDispatcher mMainDispatcher;
     private boolean mIsAnyMultiShadeExpanded;
-    private boolean mIsOcclusionTransitionRunning = false;
-    private int mDreamingToLockscreenTransitionTranslationY;
-    private int mLockscreenToDreamingTransitionTranslationY;
-    private int mGoneToDreamingTransitionTranslationY;
     private boolean mForceFlingAnimationForTest = false;
     private final SplitShadeStateController mSplitShadeStateController;
     private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
@@ -623,37 +545,6 @@
         }
     };
 
-    private final Consumer<TransitionStep> mDreamingToLockscreenTransition =
-            (TransitionStep step) -> {
-                mIsOcclusionTransitionRunning =
-                    step.getTransitionState() == TransitionState.RUNNING;
-            };
-
-    private final Consumer<TransitionStep> mOccludedToLockscreenTransition =
-            (TransitionStep step) -> {
-                mIsOcclusionTransitionRunning =
-                    step.getTransitionState() == TransitionState.RUNNING;
-            };
-
-    private final Consumer<TransitionStep> mLockscreenToDreamingTransition =
-            (TransitionStep step) -> {
-                mIsOcclusionTransitionRunning =
-                    step.getTransitionState() == TransitionState.RUNNING;
-            };
-
-    private final Consumer<TransitionStep> mGoneToDreamingTransition =
-            (TransitionStep step) -> {
-                mIsOcclusionTransitionRunning =
-                    step.getTransitionState() == TransitionState.RUNNING;
-            };
-
-
-    private final Consumer<TransitionStep> mLockscreenToOccludedTransition =
-            (TransitionStep step) -> {
-                mIsOcclusionTransitionRunning =
-                    step.getTransitionState() == TransitionState.RUNNING;
-            };
-
     private final ActivityStarter mActivityStarter;
     private final BrightnessMirrorShowingInteractor mBrightnessMirrorShowingInteractor;
 
@@ -690,12 +581,8 @@
             NotificationGutsManager gutsManager,
             NotificationsQSContainerController notificationsQSContainerController,
             NotificationStackScrollLayoutController notificationStackScrollLayoutController,
-            KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
-            KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
-            KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
             KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
             LockscreenShadeTransitionController lockscreenShadeTransitionController,
-            AuthController authController,
             ScrimController scrimController,
             UserManager userManager,
             MediaDataManager mediaDataManager,
@@ -725,11 +612,6 @@
             KeyguardClockInteractor keyguardClockInteractor,
             AlternateBouncerInteractor alternateBouncerInteractor,
             DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel,
-            OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel,
-            LockscreenToDreamingTransitionViewModel lockscreenToDreamingTransitionViewModel,
-            GoneToDreamingTransitionViewModel goneToDreamingTransitionViewModel,
-            LockscreenToOccludedTransitionViewModel lockscreenToOccludedTransitionViewModel,
-            PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
             @Main CoroutineDispatcher mainDispatcher,
             KeyguardTransitionInteractor keyguardTransitionInteractor,
             DumpManager dumpManager,
@@ -739,7 +621,6 @@
             SharedNotificationContainerInteractor sharedNotificationContainerInteractor,
             ActiveNotificationsInteractor activeNotificationsInteractor,
             ShadeAnimationInteractor shadeAnimationInteractor,
-            KeyguardViewConfigurator keyguardViewConfigurator,
             DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
             SplitShadeStateController splitShadeStateController,
             PowerInteractor powerInteractor,
@@ -764,17 +645,11 @@
         mShadeLog = shadeLogger;
         mGutsManager = gutsManager;
         mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
-        mOccludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel;
-        mLockscreenToDreamingTransitionViewModel = lockscreenToDreamingTransitionViewModel;
-        mGoneToDreamingTransitionViewModel = goneToDreamingTransitionViewModel;
-        mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
-        mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
         mSharedNotificationContainerInteractor = sharedNotificationContainerInteractor;
         mActiveNotificationsInteractor = activeNotificationsInteractor;
         mKeyguardInteractor = keyguardInteractor;
         mPowerInteractor = powerInteractor;
-        mKeyguardViewConfigurator = keyguardViewConfigurator;
         mClockPositionAlgorithm = keyguardClockPositionAlgorithm;
         mNaturalScrollingSettingObserver = naturalScrollingSettingObserver;
         mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@@ -837,15 +712,11 @@
         mNavigationBarController = navigationBarController;
         mNotificationsQSContainerController.init();
         mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
-        mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
         mKeyguardStatusBarViewComponentFactory = keyguardStatusBarViewComponentFactory;
         mDepthController = notificationShadeDepthController;
         mContentResolver = contentResolver;
-        mKeyguardQsUserSwitchComponentFactory = keyguardQsUserSwitchComponentFactory;
-        mKeyguardUserSwitcherComponentFactory = keyguardUserSwitcherComponentFactory;
         mFragmentService = fragmentService;
         mStatusBarService = statusBarService;
-        mSettingsChangeObserver = new SettingsChangeObserver(handler);
         mSplitShadeStateController = splitShadeStateController;
         mSplitShadeEnabled =
                 mSplitShadeStateController.shouldUseSplitNotificationShade(mResources);
@@ -874,22 +745,12 @@
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
         dynamicPrivacyController.addListener(this::onDynamicPrivacyChanged);
         quickSettingsController.setExpansionHeightListener(this::onQsSetExpansionHeightCalled);
-        quickSettingsController.setQsStateUpdateListener(this::onQsStateUpdated);
         quickSettingsController.setApplyClippingImmediatelyListener(
                 this::onQsClippingImmediatelyApplied);
         quickSettingsController.setFlingQsWithoutClickListener(this::onFlingQsWithoutClick);
         quickSettingsController.setExpansionHeightSetToMaxListener(this::onExpansionHeightSetToMax);
         shadeExpansionStateManager.addStateListener(this::onPanelStateChanged);
-
-        mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0);
-        mBottomAreaShadeAlphaAnimator.addUpdateListener(animation -> {
-            mBottomAreaShadeAlpha = (float) animation.getAnimatedValue();
-            updateKeyguardBottomAreaAlpha();
-        });
-        mBottomAreaShadeAlphaAnimator.setDuration(160);
-        mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
         mConversationNotificationManager = conversationNotificationManager;
-        mAuthController = authController;
         mScreenOffAnimationController = screenOffAnimationController;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
         mLastDownEvents = new NPVCDownEventState.Buffer(MAX_DOWN_EVENT_BUFFER_SIZE);
@@ -917,7 +778,6 @@
         mKeyguardUnfoldTransition = unfoldComponent.map(
                 SysUIUnfoldComponent::getKeyguardUnfoldTransition);
 
-        updateUserSwitcherFlags();
         mKeyguardClockInteractor = keyguardClockInteractor;
         KeyguardLongPressViewBinder.bind(
                 mView.requireViewById(R.id.keyguard_long_press),
@@ -979,28 +839,9 @@
                 instantCollapse();
             } else {
                 mView.animate().cancel();
-                if (!MigrateClocksToBlueprint.isEnabled()) {
-                    mView.animate()
-                            .alpha(0f)
-                            .setStartDelay(0)
-                            // Translate up by 4%.
-                            .translationY(mView.getHeight() * -0.04f)
-                            // This start delay is to give us time to animate out before
-                            // the launcher icons animation starts, so use that as our
-                            // duration.
-                            .setDuration(unlockAnimationStartDelay)
-                            .setInterpolator(EMPHASIZED_ACCELERATE)
-                            .withEndAction(() -> {
-                                instantCollapse();
-                                mView.setAlpha(1f);
-                                mView.setTranslationY(0f);
-                            })
-                            .start();
-                } else {
-                    mView.postDelayed(() -> {
-                        instantCollapse();
-                    }, unlockAnimationStartDelay);
-                }
+                mView.postDelayed(() -> {
+                    instantCollapse();
+                }, unlockAnimationStartDelay);
             }
         }
     }
@@ -1008,31 +849,13 @@
     @VisibleForTesting
     void onFinishInflate() {
         loadDimens();
-
-        FrameLayout userAvatarContainer = null;
-        KeyguardUserSwitcherView keyguardUserSwitcherView = null;
-
-        if (mKeyguardUserSwitcherEnabled && mUserManager.isUserSwitcherEnabled(
-                mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))) {
-            if (mKeyguardQsUserSwitchEnabled) {
-                ViewStub stub = mView.findViewById(R.id.keyguard_qs_user_switch_stub);
-                userAvatarContainer = (FrameLayout) stub.inflate();
-            } else {
-                ViewStub stub = mView.findViewById(R.id.keyguard_user_switcher_stub);
-                keyguardUserSwitcherView = (KeyguardUserSwitcherView) stub.inflate();
-            }
-        }
-
         mKeyguardStatusBarViewController =
                 mKeyguardStatusBarViewComponentFactory.build(
                                 mView.findViewById(R.id.keyguard_header),
                                 mShadeViewStateProvider)
                         .getKeyguardStatusBarViewController();
         mKeyguardStatusBarViewController.init();
-
         mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
-        updateViewControllers(userAvatarContainer, keyguardUserSwitcherView);
-
         mNotificationStackScrollLayoutController.setOnHeightChangedListener(
                 new NsslHeightChangedListener());
         mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener(
@@ -1046,12 +869,6 @@
             public void onFullyHiddenChanged(boolean isFullyHidden) {
                 mKeyguardStatusBarViewController.updateForHeadsUp();
             }
-
-            @Override
-            public void onDelayedDozeAmountAnimationRunning(boolean running) {
-                // On running OR finished, the animation is no longer waiting to play
-                setWillPlayDelayedDozeAmountAnimation(false);
-            }
         });
 
         mView.setRtlChangeListener(layoutDirection -> {
@@ -1071,89 +888,17 @@
                 () -> collapse(/* delayed= */ false , /* speedUpFactor= */ 1.0f));
 
         // Dreaming->Lockscreen
-        collectFlow(
-                mView,
-                mKeyguardTransitionInteractor.transition(
-                        Edge.Companion.create(DREAMING, LOCKSCREEN)),
-                mDreamingToLockscreenTransition,
-                mMainDispatcher);
         collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
                 setDreamLockscreenTransitionAlpha(mNotificationStackScrollLayoutController),
                 mMainDispatcher);
-        collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
-                mDreamingToLockscreenTransitionTranslationY),
-                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-        // Occluded->Lockscreen
         collectFlow(mView, mKeyguardTransitionInteractor.transition(
-                Edge.Companion.create(OCCLUDED, LOCKSCREEN)),
-                mOccludedToLockscreenTransition, mMainDispatcher);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
-            collectFlow(mView,
-                    mOccludedToLockscreenTransitionViewModel.getLockscreenTranslationY(),
-                    setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
-        }
-
-        // Lockscreen->Dreaming
-        collectFlow(mView, mKeyguardTransitionInteractor.transition(
-                Edge.Companion.create(LOCKSCREEN, DREAMING)),
-                mLockscreenToDreamingTransition, mMainDispatcher);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setDreamLockscreenTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-        }
-        collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
-                mLockscreenToDreamingTransitionTranslationY),
-                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
-
-        // Gone->Dreaming
-        collectFlow(mView, mKeyguardTransitionInteractor.transition(
-                Edge.Companion.create(Scenes.Gone, DREAMING),
-                        Edge.Companion.create(GONE, DREAMING)),
-                mGoneToDreamingTransition, mMainDispatcher);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
-        }
-        collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
-                mGoneToDreamingTransitionTranslationY),
-                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
-
-        // Lockscreen->Occluded
-        collectFlow(mView, mKeyguardTransitionInteractor.transition(
-                Edge.Companion.create(LOCKSCREEN, OCCLUDED)),
-                mLockscreenToOccludedTransition, mMainDispatcher);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenTranslationY(),
-                    setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
-        }
-
-        // Primary bouncer->Gone (ensures lockscreen content is not visible on successful auth)
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mPrimaryBouncerToGoneTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController,
-                            /* excludeNotifications=*/ true), mMainDispatcher);
-            collectFlow(mView, mPrimaryBouncerToGoneTransitionViewModel.getNotificationAlpha(),
-                    (Float alpha) -> {
-                        mNotificationStackScrollLayoutController.setMaxAlphaForKeyguard(alpha,
-                                "mPrimaryBouncerToGoneTransitionViewModel.getNotificationAlpha()");
-                    }, mMainDispatcher);
-        }
-
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            collectFlow(mView, mKeyguardTransitionInteractor.transition(
-                    Edge.Companion.create(AOD, LOCKSCREEN)),
-                    (TransitionStep step) -> {
-                    if (step.getTransitionState() == TransitionState.FINISHED) {
-                        updateExpandedHeightToMaxHeight();
-                    }
-                }, mMainDispatcher);
-        }
+                Edge.Companion.create(AOD, LOCKSCREEN)),
+                (TransitionStep step) -> {
+                if (step.getTransitionState() == TransitionState.FINISHED) {
+                    updateExpandedHeightToMaxHeight();
+                }
+            }, mMainDispatcher);
 
         if (com.android.systemui.Flags.bouncerUiRevamp()) {
             collectFlow(mView, mKeyguardInteractor.primaryBouncerShowing,
@@ -1189,22 +934,13 @@
         mStatusBarMinHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
         mStatusBarHeaderHeightKeyguard = Utils.getStatusBarHeaderHeightKeyguard(mView.getContext());
         mClockPositionAlgorithm.loadDimens(mView.getContext(), mResources);
-        mIndicationBottomPadding = mResources.getDimensionPixelSize(
-                R.dimen.keyguard_indication_bottom_padding);
         int statusbarHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
         mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
                 R.dimen.heads_up_status_bar_padding);
         mMaxOverscrollAmountForPulse = mResources.getDimensionPixelSize(
                 R.dimen.pulse_expansion_max_top_overshoot);
-        mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
         mSplitShadeScrimTransitionDistance = mResources.getDimensionPixelSize(
                 R.dimen.split_shade_scrim_transition_distance);
-        mDreamingToLockscreenTransitionTranslationY = mResources.getDimensionPixelSize(
-                R.dimen.dreaming_to_lockscreen_transition_lockscreen_translation_y);
-        mLockscreenToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
-                R.dimen.lockscreen_to_dreaming_transition_lockscreen_translation_y);
-        mGoneToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
-                R.dimen.gone_to_dreaming_transition_lockscreen_translation_y);
         // TODO (b/265193930): remove this and make QsController listen to NotificationPanelViews
         mQsController.loadDimens();
     }
@@ -1215,7 +951,7 @@
         if (isBouncerShowing && isExpanded()) {
             // Blur the shade much lesser than the background surface so that the surface is
             // distinguishable from the background.
-            float shadeBlurEffect = PrimaryBouncerTransition.MAX_BACKGROUND_BLUR_RADIUS / 3;
+            float shadeBlurEffect = mDepthController.getMaxBlurRadiusPx() / 3;
             mView.setRenderEffect(RenderEffect.createBlurEffect(
                     shadeBlurEffect,
                     shadeBlurEffect,
@@ -1225,70 +961,6 @@
         }
     }
 
-    private void updateViewControllers(
-            FrameLayout userAvatarView,
-            KeyguardUserSwitcherView keyguardUserSwitcherView) {
-        updateStatusViewController();
-        if (mKeyguardUserSwitcherController != null) {
-            // Try to close the switcher so that callbacks are triggered if necessary.
-            // Otherwise, NPV can get into a state where some of the views are still hidden
-            mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(false);
-        }
-
-        mKeyguardQsUserSwitchController = null;
-        mKeyguardUserSwitcherController = null;
-
-        // Re-associate the KeyguardUserSwitcherController
-        if (userAvatarView != null) {
-            KeyguardQsUserSwitchComponent userSwitcherComponent =
-                    mKeyguardQsUserSwitchComponentFactory.build(userAvatarView);
-            mKeyguardQsUserSwitchController =
-                    userSwitcherComponent.getKeyguardQsUserSwitchController();
-            mKeyguardQsUserSwitchController.init();
-            mKeyguardStatusBarViewController.setKeyguardUserSwitcherEnabled(true);
-        } else if (keyguardUserSwitcherView != null) {
-            KeyguardUserSwitcherComponent userSwitcherComponent =
-                    mKeyguardUserSwitcherComponentFactory.build(keyguardUserSwitcherView);
-            mKeyguardUserSwitcherController =
-                    userSwitcherComponent.getKeyguardUserSwitcherController();
-            mKeyguardUserSwitcherController.init();
-            mKeyguardStatusBarViewController.setKeyguardUserSwitcherEnabled(true);
-        } else {
-            mKeyguardStatusBarViewController.setKeyguardUserSwitcherEnabled(false);
-        }
-    }
-
-    /** Updates the StatusBarViewController and updates any that depend on it. */
-    public void updateStatusViewController() {
-        // Re-associate the KeyguardStatusViewController
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            // Need a shared controller until mKeyguardStatusViewController can be removed from
-            // here, due to important state being set in that controller. Rebind in order to pick
-            // up config changes
-            mKeyguardStatusViewController =
-                    mKeyguardViewConfigurator.getKeyguardStatusViewController();
-        } else {
-            KeyguardStatusView keyguardStatusView = mView.getRootView().findViewById(
-                    R.id.keyguard_status_view);
-            KeyguardStatusViewComponent statusViewComponent =
-                    mKeyguardStatusViewComponentFactory.build(keyguardStatusView,
-                            mView.getContext().getDisplay());
-            mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
-            mKeyguardStatusViewController.init();
-
-            mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
-            mKeyguardStatusViewController.getView().addOnLayoutChangeListener(
-                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                    int oldHeight = oldBottom - oldTop;
-                    if (v.getHeight() != oldHeight) {
-                        mNotificationStackScrollLayoutController.animateNextTopPaddingChange();
-                    }
-                });
-
-            updateClockAppearance();
-        }
-    }
-
     @Override
     public void updateResources() {
         Trace.beginSection("NSSLC#updateResources");
@@ -1317,16 +989,9 @@
 
     private void onSplitShadeEnabledChanged() {
         mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
-        }
         // Reset any left over overscroll state. It is a rare corner case but can happen.
         mQsController.setOverScrollAmount(0);
         mScrimController.setNotificationsOverScrollAmount(0);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mNotificationStackScrollLayoutController.setOverExpansion(0);
-            mNotificationStackScrollLayoutController.setOverScrollAmount(0);
-        }
 
         // when we switch between split shade and regular shade we want to enforce setting qs to
         // the default state: expanded for split shade and collapsed otherwise
@@ -1344,9 +1009,6 @@
         }
         updateClockAppearance();
         mQsController.updateQsState();
-        if (!MigrateClocksToBlueprint.isEnabled() && !FooterViewRefactor.isEnabled()) {
-            mNotificationStackScrollLayoutController.updateFooter();
-        }
     }
 
     private View reInflateStub(int viewId, int stubId, int layoutId, boolean enabled) {
@@ -1375,81 +1037,9 @@
     @VisibleForTesting
     void reInflateViews() {
         debugLog("reInflateViews");
-        // Re-inflate the status view group.
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            KeyguardStatusView keyguardStatusView =
-                    mNotificationContainerParent.findViewById(R.id.keyguard_status_view);
-            int statusIndex = mNotificationContainerParent.indexOfChild(keyguardStatusView);
-            mNotificationContainerParent.removeView(keyguardStatusView);
-            keyguardStatusView = (KeyguardStatusView) mLayoutInflater.inflate(
-                    R.layout.keyguard_status_view, mNotificationContainerParent, false);
-            mNotificationContainerParent.addView(keyguardStatusView, statusIndex);
-
-            attachSplitShadeMediaPlayerContainer(
-                    keyguardStatusView.findViewById(R.id.status_view_media_container));
-        }
-
-        // we need to update KeyguardStatusView constraints after reinflating it
         updateResources();
-
-        // Re-inflate the keyguard user switcher group.
-        updateUserSwitcherFlags();
-        boolean isUserSwitcherEnabled = mUserManager.isUserSwitcherEnabled(
-                mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user));
-        boolean showQsUserSwitch = mKeyguardQsUserSwitchEnabled && isUserSwitcherEnabled;
-        boolean showKeyguardUserSwitcher =
-                !mKeyguardQsUserSwitchEnabled
-                        && mKeyguardUserSwitcherEnabled
-                        && isUserSwitcherEnabled;
-        FrameLayout userAvatarView = (FrameLayout) reInflateStub(
-                R.id.keyguard_qs_user_switch_view /* viewId */,
-                R.id.keyguard_qs_user_switch_stub /* stubId */,
-                R.layout.keyguard_qs_user_switch /* layoutId */,
-                showQsUserSwitch /* enabled */);
-        KeyguardUserSwitcherView keyguardUserSwitcherView =
-                (KeyguardUserSwitcherView) reInflateStub(
-                        R.id.keyguard_user_switcher_view /* viewId */,
-                        R.id.keyguard_user_switcher_stub /* stubId */,
-                        R.layout.keyguard_user_switcher /* layoutId */,
-                        showKeyguardUserSwitcher /* enabled */);
-
-        updateViewControllers(userAvatarView, keyguardUserSwitcherView);
         mStatusBarStateListener.onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
                 mStatusBarStateController.getInterpolatedDozeAmount());
-
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
-                    mBarState,
-                    false,
-                    false,
-                    mBarState);
-        }
-        if (mKeyguardQsUserSwitchController != null) {
-            mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
-                    mBarState,
-                    false,
-                    false,
-                    mBarState);
-        }
-        if (mKeyguardUserSwitcherController != null) {
-            mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
-                    mBarState,
-                    false,
-                    false,
-                    mBarState);
-        }
-    }
-
-    private void attachSplitShadeMediaPlayerContainer(FrameLayout container) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        mKeyguardMediaController.attachSplitShadeContainer(container);
-    }
-
-    @VisibleForTesting
-    void setMaxDisplayedNotifications(int maxAllowed) {
-        mMaxAllowedKeyguardNotifications = maxAllowed;
     }
 
     @VisibleForTesting
@@ -1457,33 +1047,6 @@
         return mIsFlinging;
     }
 
-    private void updateMaxDisplayedNotifications(boolean recompute) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-
-        if (recompute) {
-            setMaxDisplayedNotifications(Math.max(computeMaxKeyguardNotifications(), 1));
-        } else {
-            if (SPEW_LOGCAT) Log.d(TAG, "Skipping computeMaxKeyguardNotifications() by request");
-        }
-
-        if (isKeyguardShowing() && !mKeyguardBypassController.getBypassEnabled()) {
-            mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(
-                    mMaxAllowedKeyguardNotifications);
-            mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(
-                    mKeyguardNotificationBottomPadding);
-        } else {
-            // no max when not on the keyguard
-            mNotificationStackScrollLayoutController.setMaxDisplayedNotifications(-1);
-            mNotificationStackScrollLayoutController.setKeyguardBottomPaddingForDebug(-1f);
-        }
-    }
-
-    private boolean shouldAvoidChangingNotificationsCount() {
-        return mUnlockedScreenOffAnimationController.isAnimationPlaying();
-    }
-
     /** Sets a listener to be notified when the shade starts opening or finishes closing. */
     public void setOpenCloseListener(OpenCloseListener openCloseListener) {
         SceneContainerFlag.assertInLegacyMode();
@@ -1563,88 +1126,28 @@
     }
 
     private void updateClockAppearance() {
-        int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
-        boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
-        boolean shouldAnimateClockChange = mScreenOffAnimationController.shouldAnimateClockChange();
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardClockInteractor.setClockSize(computeDesiredClockSize());
-        } else {
-            mKeyguardStatusViewController.displayClock(computeDesiredClockSize(),
-                    shouldAnimateClockChange);
-        }
+        mKeyguardClockInteractor.setClockSize(computeDesiredClockSize());
         updateKeyguardStatusViewAlignment(/* animate= */true);
-        int userSwitcherHeight = mKeyguardQsUserSwitchController != null
-                ? mKeyguardQsUserSwitchController.getUserIconHeight() : 0;
-        if (mKeyguardUserSwitcherController != null) {
-            userSwitcherHeight = mKeyguardUserSwitcherController.getHeight();
-        }
-        float expandedFraction =
-                mScreenOffAnimationController.shouldExpandNotifications()
-                        ? 1.0f : getExpandedFraction();
+
         float darkAmount =
                 mScreenOffAnimationController.shouldExpandNotifications()
                         ? 1.0f : mInterpolatedDarkAmount;
 
-        float udfpsAodTopLocation = -1f;
-        if (mUpdateMonitor.isUdfpsEnrolled() && mAuthController.getUdfpsLocation() != null) {
-            udfpsAodTopLocation = mAuthController.getUdfpsLocation().y
-                    - mAuthController.getUdfpsRadius() - mUdfpsMaxYBurnInOffset;
-        }
-
         mClockPositionAlgorithm.setup(
-                mStatusBarHeaderHeightKeyguard,
-                expandedFraction,
-                mKeyguardStatusViewController.getLockscreenHeight(),
-                userSwitcherHeight,
-                userSwitcherPreferredY,
                 darkAmount, mOverStretchAmount,
-                bypassEnabled,
+                mKeyguardBypassController.getBypassEnabled(),
                 mQsController.getHeaderHeight(),
-                mQsController.computeExpansionFraction(),
-                mDisplayTopInset,
-                mSplitShadeEnabled,
-                udfpsAodTopLocation,
-                mKeyguardStatusViewController.getClockBottom(mStatusBarHeaderHeightKeyguard),
-                mKeyguardStatusViewController.isClockTopAligned());
+                mSplitShadeEnabled);
         mClockPositionAlgorithm.run(mClockPositionResult);
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.setLockscreenClockY(
-                    mClockPositionAlgorithm.getExpandedPreferredClockY());
-        }
-
-        boolean animate = !SceneContainerFlag.isEnabled()
-                && mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
-        boolean animateClock = (animate || mAnimateNextPositionUpdate) && shouldAnimateClockChange;
-
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.updatePosition(
-                    mClockPositionResult.clockX, mClockPositionResult.clockY,
-                    mClockPositionResult.clockScale, animateClock);
-        }
-        if (mKeyguardQsUserSwitchController != null) {
-            mKeyguardQsUserSwitchController.updatePosition(
-                    mClockPositionResult.clockX,
-                    mClockPositionResult.userSwitchY,
-                    animateClock);
-        }
-        if (mKeyguardUserSwitcherController != null) {
-            mKeyguardUserSwitcherController.updatePosition(
-                    mClockPositionResult.clockX,
-                    mClockPositionResult.userSwitchY,
-                    animateClock);
-        }
-        updateNotificationTranslucency();
-        updateClock();
     }
 
     KeyguardClockPositionAlgorithm.Result getClockPositionResult() {
         return mClockPositionResult;
     }
 
-    @ClockSize
-    private int computeDesiredClockSize() {
+    private ClockSize computeDesiredClockSize() {
         if (shouldForceSmallClock()) {
-            return SMALL;
+            return ClockSize.SMALL;
         }
 
         if (mSplitShadeEnabled) {
@@ -1653,34 +1156,22 @@
         return computeDesiredClockSizeForSingleShade();
     }
 
-    @ClockSize
-    private int computeDesiredClockSizeForSingleShade() {
+    private ClockSize computeDesiredClockSizeForSingleShade() {
         if (hasVisibleNotifications()) {
-            return SMALL;
+            return ClockSize.SMALL;
         }
-        return LARGE;
+        return ClockSize.LARGE;
     }
 
-    @ClockSize
-    private int computeDesiredClockSizeForSplitShade() {
+    private ClockSize computeDesiredClockSizeForSplitShade() {
         // Media is not visible to the user on AOD.
         boolean isMediaVisibleToUser =
                 mMediaDataManager.hasActiveMediaOrRecommendation() && !isOnAod();
         if (isMediaVisibleToUser) {
             // When media is visible, it overlaps with the large clock. Use small clock instead.
-            return SMALL;
+            return ClockSize.SMALL;
         }
-        // To prevent the weather clock from overlapping with the notification shelf on AOD, we use
-        // the small clock here
-        // With migrateClocksToBlueprint, weather clock will have behaviors similar to other clocks
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
-            if (mKeyguardStatusViewController.isLargeClockBlockingNotificationShelf()
-                    && hasVisibleNotifications() && (isOnAod() || bypassEnabled)) {
-                return SMALL;
-            }
-        }
-        return LARGE;
+        return ClockSize.LARGE;
     }
 
     private boolean shouldForceSmallClock() {
@@ -1693,13 +1184,7 @@
     private void updateKeyguardStatusViewAlignment(boolean animate) {
         boolean shouldBeCentered = shouldKeyguardStatusViewBeCentered();
         mKeyguardUnfoldTransition.ifPresent(t -> t.setStatusViewCentered(shouldBeCentered));
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardInteractor.setClockShouldBeCentered(shouldBeCentered);
-            return;
-        }
-        ConstraintLayout layout = mNotificationContainerParent;
-        mKeyguardStatusViewController.updateAlignment(
-                layout, mSplitShadeEnabled, shouldBeCentered, animate);
+        mKeyguardInteractor.setClockShouldBeCentered(shouldBeCentered);
     }
 
     private boolean shouldKeyguardStatusViewBeCentered() {
@@ -1719,31 +1204,15 @@
             // Pulsing notification appears on the right. Move clock left to avoid overlap.
             return false;
         }
-        if (mWillPlayDelayedDozeAmountAnimation) {
-            return true;
-        }
         // "Visible" notifications are actually not visible on AOD (unless pulsing), so it is safe
         // to center the clock without overlap.
         return isOnAod();
     }
 
-    @Override
-    public void setWillPlayDelayedDozeAmountAnimation(boolean willPlay) {
-        if (mWillPlayDelayedDozeAmountAnimation == willPlay) return;
-
-        mWillPlayDelayedDozeAmountAnimation = willPlay;
-        mWakeUpCoordinator.logDelayingClockWakeUpAnimation(willPlay);
-        mKeyguardMediaController.setDozeWakeUpAnimationWaiting(willPlay);
-
-        // Once changing this value, see if we should move the clock.
-        positionClockAndNotifications();
-    }
-
     private boolean isOnAod() {
         return mDozing && mDozeParameters.getAlwaysOn();
     }
 
-
     private boolean hasVisibleNotifications() {
         if (FooterViewRefactor.isEnabled()) {
             return mActiveNotificationsInteractor.getAreAnyNotificationsPresentValue()
@@ -1755,128 +1224,6 @@
         }
     }
 
-    /** Returns space between top of lock icon and bottom of NotificationStackScrollLayout. */
-    private float getLockIconPadding() {
-        float lockIconPadding = 0f;
-        View deviceEntryIconView = mKeyguardViewConfigurator.getKeyguardRootView()
-                .findViewById(R.id.device_entry_icon_view);
-        if (deviceEntryIconView != null) {
-            lockIconPadding = mNotificationStackScrollLayoutController.getBottom()
-                - deviceEntryIconView.getTop();
-        }
-        return lockIconPadding;
-    }
-
-    /** Returns space available to show notifications on lockscreen. */
-    @VisibleForTesting
-    float getVerticalSpaceForLockscreenNotifications() {
-        final float lockIconPadding = getLockIconPadding();
-
-        float bottomPadding = Math.max(lockIconPadding,
-                Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding));
-        mKeyguardNotificationBottomPadding = bottomPadding;
-
-        float staticTopPadding = mClockPositionAlgorithm.getLockscreenNotifPadding(
-                mNotificationStackScrollLayoutController.getTop());
-
-        mKeyguardNotificationTopPadding = staticTopPadding;
-
-        // To debug the available space, enable debug lines in this class. If you change how the
-        // available space is calculated, please also update those lines.
-        final float verticalSpace =
-                mNotificationStackScrollLayoutController.getHeight()
-                        - staticTopPadding
-                        - bottomPadding;
-
-        if (SPEW_LOGCAT) {
-            Log.i(TAG, "\n");
-            Log.i(TAG, "staticTopPadding[" + staticTopPadding
-                    + "] = Clock.padding["
-                    + mClockPositionAlgorithm.getLockscreenNotifPadding(
-                            mNotificationStackScrollLayoutController.getTop())
-                    + "]"
-            );
-            Log.i(TAG, "bottomPadding[" + bottomPadding
-                    + "] = max(ambientIndicationBottomPadding[" + mAmbientIndicationBottomPadding
-                    + "], mIndicationBottomPadding[" + mIndicationBottomPadding
-                    + "], lockIconPadding[" + lockIconPadding
-                    + "])"
-            );
-            Log.i(TAG, "verticalSpaceForNotifications[" + verticalSpace
-                    + "] = NSSL.height[" + mNotificationStackScrollLayoutController.getHeight()
-                    + "] - staticTopPadding[" + staticTopPadding
-                    + "] - bottomPadding[" + bottomPadding
-                    + "]"
-            );
-        }
-        return verticalSpace;
-    }
-
-    /** Returns extra space available to show the shelf on lockscreen */
-    @VisibleForTesting
-    float getVerticalSpaceForLockscreenShelf() {
-        if (mSplitShadeEnabled) {
-            return 0f;
-        }
-        final float lockIconPadding = getLockIconPadding();
-
-        final float noShelfOverlapBottomPadding =
-                Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
-
-        final float extraSpaceForShelf = lockIconPadding - noShelfOverlapBottomPadding;
-
-        if (extraSpaceForShelf > 0f) {
-            return Math.min(getShelfHeight(), extraSpaceForShelf);
-        }
-        return 0f;
-    }
-
-    /**
-     * @return Maximum number of notifications that can fit on keyguard.
-     */
-    @VisibleForTesting
-    int computeMaxKeyguardNotifications() {
-        if (mAmbientState.getFractionToShade() > 0) {
-            if (SPEW_LOGCAT) {
-                Log.v(TAG, "Internally skipping computeMaxKeyguardNotifications()"
-                        + " fractionToShade=" + mAmbientState.getFractionToShade()
-                );
-            }
-            return mMaxAllowedKeyguardNotifications;
-        }
-        return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications(
-                mNotificationStackScrollLayoutController.getView(),
-                getVerticalSpaceForLockscreenNotifications(),
-                getVerticalSpaceForLockscreenShelf(),
-                getShelfHeight()
-        );
-    }
-
-    private int getShelfHeight() {
-        return mNotificationStackScrollLayoutController.getShelfHeight();
-    }
-
-    private void updateClock() {
-        if (mIsOcclusionTransitionRunning) {
-            return;
-        }
-        float alpha = mClockPositionResult.clockAlpha * mKeyguardOnlyContentAlpha;
-        mKeyguardStatusViewController.setAlpha(alpha);
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            // TODO (b/296373478) This is for split shade media movement.
-        } else {
-            mKeyguardStatusViewController
-                .setTranslationY(mKeyguardOnlyTransitionTranslationY, /* excludeMedia= */true);
-        }
-
-        if (mKeyguardQsUserSwitchController != null) {
-            mKeyguardQsUserSwitchController.setAlpha(alpha);
-        }
-        if (mKeyguardUserSwitcherController != null) {
-            mKeyguardUserSwitcherController.setAlpha(alpha);
-        }
-    }
-
     @Override
     public void transitionToExpandedShade(long delay) {
         mNotificationStackScrollLayoutController.goToFullShade(delay);
@@ -2318,17 +1665,6 @@
         return mPowerInteractor.getDetailedWakefulness().getValue();
     }
 
-    @VisibleForTesting
-    void maybeAnimateBottomAreaAlpha() {
-        mBottomAreaShadeAlphaAnimator.cancel();
-        if (mBarState == StatusBarState.SHADE_LOCKED) {
-            mBottomAreaShadeAlphaAnimator.setFloatValues(mBottomAreaShadeAlpha, 0.0f);
-            mBottomAreaShadeAlphaAnimator.start();
-        } else {
-            mBottomAreaShadeAlpha = 1f;
-        }
-    }
-
     /**
      * When the back gesture triggers a fully-expanded shade --> QQS shade collapse transition,
      * the expansionFraction goes down from 1.0 --> 0.0 (collapsing), so the current "squish" amount
@@ -2408,7 +1744,7 @@
         }
 
         if (!mKeyguardBypassController.getBypassEnabled()) {
-            if (MigrateClocksToBlueprint.isEnabled() && !mSplitShadeEnabled) {
+            if (!mSplitShadeEnabled) {
                 return (int) mKeyguardInteractor.getNotificationContainerBounds()
                         .getValue().getTop();
             }
@@ -2430,23 +1766,11 @@
         return mBarState == KEYGUARD;
     }
 
-    float getKeyguardNotificationTopPadding() {
-        return mKeyguardNotificationTopPadding;
-    }
-
-    float getKeyguardNotificationBottomPadding() {
-        return mKeyguardNotificationBottomPadding;
-    }
-
     void requestScrollerTopPaddingUpdate(boolean animate) {
         if (!SceneContainerFlag.isEnabled()) {
             float padding = mQsController.calculateNotificationsTopPadding(mIsExpandingOrCollapsing,
                     getKeyguardNotificationStaticPadding(), mExpandedFraction);
-            if (MigrateClocksToBlueprint.isEnabled()) {
-                mSharedNotificationContainerInteractor.setTopPosition(padding);
-            } else {
-                mNotificationStackScrollLayoutController.updateTopPadding(padding, animate);
-            }
+            mSharedNotificationContainerInteractor.setTopPosition(padding);
         }
 
         if (isKeyguardShowing()
@@ -2457,27 +1781,10 @@
     }
 
     @Override
-    public void setKeyguardTransitionProgress(float keyguardAlpha, int keyguardTranslationY) {
-        mKeyguardOnlyContentAlpha = Interpolators.ALPHA_IN.getInterpolation(keyguardAlpha);
-        mKeyguardOnlyTransitionTranslationY = keyguardTranslationY;
-        if (mBarState == KEYGUARD) {
-            // If the animator is running, it's already fading out the content and this is a reset
-            mBottomAreaShadeAlpha = mKeyguardOnlyContentAlpha;
-            updateKeyguardBottomAreaAlpha();
-        }
-        updateClock();
-    }
-
-    @Override
     public void setKeyguardStatusBarAlpha(float alpha) {
         mKeyguardStatusBarViewController.setAlpha(alpha);
     }
 
-    /** */
-    float getKeyguardOnlyContentAlpha() {
-        return mKeyguardOnlyContentAlpha;
-    }
-
     @VisibleForTesting
     boolean canCollapsePanelOnTouch() {
         if (!mQsController.getExpanded() && mBarState == KEYGUARD) {
@@ -2578,7 +1885,6 @@
         }
         updateExpandedHeight(expandedHeight);
         updateHeader();
-        updateNotificationTranslucency();
         updatePanelExpanded();
         updateGestureExclusionRect();
         if (DEBUG_DRAWABLE) {
@@ -2616,35 +1922,14 @@
         int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin;
 
         if (mBarState == KEYGUARD) {
-            int minKeyguardPanelBottom = mClockPositionAlgorithm.getLockscreenStatusViewHeight()
-                    + mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
+            int minKeyguardPanelBottom = mNotificationStackScrollLayoutController
+                    .getIntrinsicContentHeight();
             return Math.max(maxHeight, minKeyguardPanelBottom);
         } else {
             return maxHeight;
         }
     }
 
-    private void updateNotificationTranslucency() {
-        if (mIsOcclusionTransitionRunning) {
-            return;
-        }
-
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            float alpha = 1f;
-            if (mClosingWithAlphaFadeOut && !mExpandingFromHeadsUp
-                && !mHeadsUpManager.hasPinnedHeadsUp()) {
-                alpha = getFadeoutAlpha();
-            }
-            if (mBarState == KEYGUARD
-                && !mKeyguardBypassController.getBypassEnabled()
-                && !mQsController.getFullyExpanded()) {
-                alpha *= mClockPositionResult.clockAlpha;
-            }
-            mNotificationStackScrollLayoutController.setMaxAlphaForKeyguard(alpha,
-                    "NPVC.updateNotificationTranslucency()");
-        }
-    }
-
     private float getFadeoutAlpha() {
         float alpha;
         if (mQsController.getMinExpansionHeight() == 0) {
@@ -2664,28 +1949,6 @@
         mQsController.updateExpansion();
     }
 
-    private void updateKeyguardBottomAreaAlpha() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return;
-        }
-        if (mIsOcclusionTransitionRunning) {
-            return;
-        }
-        // There are two possible panel expansion behaviors:
-        // • User dragging up to unlock: we want to fade out as quick as possible
-        //   (ALPHA_EXPANSION_THRESHOLD) to avoid seeing the bouncer over the bottom area.
-        // • User tapping on lock screen: bouncer won't be visible but panel expansion will
-        //   change due to "unlock hint animation." In this case, fading out the bottom area
-        //   would also hide the message that says "swipe to unlock," we don't want to do that.
-        float expansionAlpha = MathUtils.constrainedMap(0f, 1f,
-                KeyguardBouncerConstants.ALPHA_EXPANSION_THRESHOLD, 1f,
-                getExpandedFraction());
-
-        float alpha = Math.min(expansionAlpha, 1 - mQsController.computeExpansionFraction());
-        alpha *= mBottomAreaShadeAlpha;
-        mKeyguardInteractor.setAlpha(alpha);
-    }
-
     private void onExpandingFinished() {
         if (!SceneContainerFlag.isEnabled()) {
             mNotificationStackScrollLayoutController.onExpansionStopped();
@@ -2896,13 +2159,6 @@
         }
     }
 
-    @Override
-    public void onScreenTurningOn() {
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.dozeTimeTick();
-        }
-    }
-
     private void onMiddleClicked() {
         switch (mBarState) {
             case KEYGUARD:
@@ -3008,7 +2264,6 @@
         if (!SceneContainerFlag.isEnabled()) {
             mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight);
         }
-        updateKeyguardBottomAreaAlpha();
         updateStatusBarIcons();
     }
 
@@ -3135,10 +2390,6 @@
         mKeyguardStatusBarViewController.setDozing(mDozing);
         mQsController.setDozing(mDozing);
 
-        if (dozing) {
-            mBottomAreaShadeAlphaAnimator.cancel();
-        }
-
         if (mBarState == KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) {
             updateDozingVisibilities(animate);
         }
@@ -3168,32 +2419,6 @@
         updateKeyguardStatusViewAlignment(/* animate= */ true);
     }
 
-    @Override
-    public void setAmbientIndicationTop(int ambientIndicationTop, boolean ambientTextVisible) {
-        int ambientIndicationBottomPadding = 0;
-        if (ambientTextVisible) {
-            int stackBottom = mNotificationStackScrollLayoutController.getBottom();
-            ambientIndicationBottomPadding = stackBottom - ambientIndicationTop;
-        }
-        if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
-            mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
-            updateMaxDisplayedNotifications(true);
-        }
-    }
-
-    public void dozeTimeTick() {
-        if (!MigrateClocksToBlueprint.isEnabled()) {
-            mKeyguardStatusViewController.dozeTimeTick();
-        }
-        if (mInterpolatedDarkAmount > 0) {
-            positionClockAndNotifications();
-        }
-    }
-
-    void setStatusAccessibilityImportance(int mode) {
-        mKeyguardStatusViewController.setStatusAccessibilityImportance(mode);
-    }
-
     public void performHapticFeedback(int constant) {
         if (msdlFeedback()) {
             MSDLToken token;
@@ -3248,24 +2473,6 @@
     }
 
     @Override
-    public void startBouncerPreHideAnimation() {
-        if (mKeyguardQsUserSwitchController != null) {
-            mKeyguardQsUserSwitchController.setKeyguardQsUserSwitchVisibility(
-                    mBarState,
-                    true /* keyguardFadingAway */,
-                    false /* goingToFullShade */,
-                    mBarState);
-        }
-        if (mKeyguardUserSwitcherController != null) {
-            mKeyguardUserSwitcherController.setKeyguardUserSwitcherVisibility(
-                    mBarState,
-                    true /* keyguardFadingAway */,
-                    false /* goingToFullShade */,
-                    mBarState);
-        }
-    }
-
-    @Override
     public ShadeFoldAnimatorImpl getShadeFoldAnimator() {
         return mShadeFoldAnimator;
     }
@@ -3275,12 +2482,7 @@
         /** Updates the views to the initial state for the fold to AOD animation. */
         @Override
         public void prepareFoldToAodAnimation() {
-            if (MigrateClocksToBlueprint.isEnabled()) {
-                setDozing(true /* dozing */, false /* animate */);
-            } else {
-                // Force show AOD UI even if we are not locked
-                showAodUi();
-            }
+            setDozing(true /* dozing */, false /* animate */);
 
             // Move the content of the AOD all the way to the left
             // so we can animate to the initial position
@@ -3300,14 +2502,7 @@
         @Override
         public void startFoldToAodAnimation(
                 Runnable startAction, Runnable endAction, Runnable cancelAction) {
-            if (MigrateClocksToBlueprint.isEnabled()) {
-                return;
-            }
 
-            buildViewAnimator(startAction, endAction, cancelAction)
-                    .setUpdateListener(anim -> mKeyguardStatusViewController
-                            .animateFoldToAod(anim.getAnimatedFraction()))
-                    .start();
         }
 
         /**
@@ -3353,13 +2548,6 @@
             resetAlpha();
             resetTranslation();
         }
-
-        /** Returns the NotificationPanelView. */
-        @Override
-        public ViewGroup getView() {
-            // TODO(b/254878364): remove this method, or at least reduce references to it.
-            return mView;
-        }
     }
 
     @Override
@@ -3387,15 +2575,8 @@
         ipw.print("isTracking()="); ipw.println(isTracking());
         ipw.print("mExpanding="); ipw.println(mExpanding);
         ipw.print("mSplitShadeEnabled="); ipw.println(mSplitShadeEnabled);
-        ipw.print("mKeyguardNotificationBottomPadding=");
-        ipw.println(mKeyguardNotificationBottomPadding);
-        ipw.print("mKeyguardNotificationTopPadding="); ipw.println(mKeyguardNotificationTopPadding);
-        ipw.print("mMaxAllowedKeyguardNotifications=");
-        ipw.println(mMaxAllowedKeyguardNotifications);
         ipw.print("mAnimateNextPositionUpdate="); ipw.println(mAnimateNextPositionUpdate);
         ipw.print("isPanelExpanded()="); ipw.println(isPanelExpanded());
-        ipw.print("mKeyguardQsUserSwitchEnabled="); ipw.println(mKeyguardQsUserSwitchEnabled);
-        ipw.print("mKeyguardUserSwitcherEnabled="); ipw.println(mKeyguardUserSwitcherEnabled);
         ipw.print("mDozing="); ipw.println(mDozing);
         ipw.print("mDozingOnDown="); ipw.println(mDozingOnDown);
         ipw.print("mBouncerShowing="); ipw.println(mBouncerShowing);
@@ -3417,8 +2598,6 @@
         ipw.print("mClosingWithAlphaFadeOut="); ipw.println(mClosingWithAlphaFadeOut);
         ipw.print("mHeadsUpAnimatingAway="); ipw.println(mHeadsUpAnimatingAway);
         ipw.print("mShowIconsWhenExpanded="); ipw.println(mShowIconsWhenExpanded);
-        ipw.print("mIndicationBottomPadding="); ipw.println(mIndicationBottomPadding);
-        ipw.print("mAmbientIndicationBottomPadding="); ipw.println(mAmbientIndicationBottomPadding);
         ipw.print("mIsFullWidth="); ipw.println(mIsFullWidth);
         ipw.print("mBlockingExpansionForCurrentTouch=");
         ipw.println(mBlockingExpansionForCurrentTouch);
@@ -3429,16 +2608,11 @@
         ipw.print("mPulsing="); ipw.println(mPulsing);
         ipw.print("mStackScrollerMeasuringPass="); ipw.println(mStackScrollerMeasuringPass);
         ipw.print("mPanelAlpha="); ipw.println(mPanelAlpha);
-        ipw.print("mBottomAreaShadeAlpha="); ipw.println(mBottomAreaShadeAlpha);
         ipw.print("mHeadsUpInset="); ipw.println(mHeadsUpInset);
         ipw.print("mHeadsUpPinnedMode="); ipw.println(mHeadsUpPinnedMode);
         ipw.print("mAllowExpandForSmallExpansion="); ipw.println(mAllowExpandForSmallExpansion);
         ipw.print("mMaxOverscrollAmountForPulse="); ipw.println(mMaxOverscrollAmountForPulse);
         ipw.print("mIsPanelCollapseOnQQS="); ipw.println(mIsPanelCollapseOnQQS);
-        ipw.print("mKeyguardOnlyContentAlpha="); ipw.println(mKeyguardOnlyContentAlpha);
-        ipw.print("mKeyguardOnlyTransitionTranslationY=");
-        ipw.println(mKeyguardOnlyTransitionTranslationY);
-        ipw.print("mUdfpsMaxYBurnInOffset="); ipw.println(mUdfpsMaxYBurnInOffset);
         ipw.print("mIsGestureNavigation="); ipw.println(mIsGestureNavigation);
         ipw.print("mOldLayoutDirection="); ipw.println(mOldLayoutDirection);
         ipw.print("mMinFraction="); ipw.println(mMinFraction);
@@ -3507,7 +2681,6 @@
 
         mGestureRecorder = recorder;
         mHideExpandedRunnable = hideExpandedRunnable;
-        updateMaxDisplayedNotifications(true);
     }
 
     @Override
@@ -3552,31 +2725,6 @@
     }
 
     @Override
-    public boolean closeUserSwitcherIfOpen() {
-        if (mKeyguardUserSwitcherController != null) {
-            return mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(
-                    true /* animate */);
-        }
-        return false;
-    }
-
-    private void updateUserSwitcherFlags() {
-        mKeyguardUserSwitcherEnabled = mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher);
-        mKeyguardQsUserSwitchEnabled =
-                mKeyguardUserSwitcherEnabled
-                        && mFeatureFlags.isEnabled(Flags.QS_USER_DETAIL_SHORTCUT);
-    }
-
-    private void registerSettingsChangeListener() {
-        mContentResolver.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED),
-                /* notifyForDescendants */ false,
-                mSettingsChangeObserver
-        );
-    }
-
-    @Override
     public void updateSystemUiStateFlags() {
         if (SysUiState.DEBUG) {
             Log.d(TAG, "Updating panel sysui state flags: fullyExpanded="
@@ -3678,7 +2826,7 @@
      */
     private boolean isDirectionUpwards(float x, float y) {
         float xDiff = x - mInitialExpandX;
-        float yDiff = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
+        float yDiff = y - mInitialExpandY;
         if (yDiff >= 0) {
             return false;
         }
@@ -3716,7 +2864,7 @@
                 || (!isFullyExpanded() && !isFullyCollapsed())
                 || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) {
             mVelocityTracker.computeCurrentVelocity(1000);
-            float vel = (mIsTrackpadReverseScroll ? -1 : 1) * mVelocityTracker.getYVelocity();
+            float vel = mVelocityTracker.getYVelocity();
             float vectorVel = (float) Math.hypot(
                     mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
 
@@ -3755,7 +2903,7 @@
                 mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
                 mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
             }
-            float dy = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
+            float dy = y - mInitialExpandY;
             @Classifier.InteractionType int interactionType = vel == 0 ? GENERIC
                     : dy > 0 ? QUICK_SETTINGS
                             : (mKeyguardStateController.canDismissLockScreen()
@@ -3784,7 +2932,7 @@
 
     private float getCurrentExpandVelocity() {
         mVelocityTracker.computeCurrentVelocity(1000);
-        return (mIsTrackpadReverseScroll ? -1 : 1) * mVelocityTracker.getYVelocity();
+        return mVelocityTracker.getYVelocity();
     }
 
     private void endClosing() {
@@ -3898,18 +3046,6 @@
                 mExpandLatencyTracking = false;
             }
             float maxPanelHeight = getMaxPanelTransitionDistance();
-            if (mHeightAnimator == null && !MigrateClocksToBlueprint.isEnabled()) {
-                // MigrateClocksToBlueprint - There is an edge case where swiping up slightly,
-                // and then swiping down will trigger overscroll logic. Even without this flag
-                // enabled, the notifications can then run into UDFPS. At this point it is
-                // safer to remove overscroll for this one case to prevent overlap.
-
-                // Split shade has its own overscroll logic
-                if (isTracking()) {
-                    float overExpansionPixels = Math.max(0, h - maxPanelHeight);
-                    setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
-                }
-            }
             mExpandedHeight = Math.min(h, maxPanelHeight);
             // If we are closing the panel and we are almost there due to a slow decelerating
             // interpolator, abort the animation.
@@ -4226,9 +3362,6 @@
 
     void onQsExpansionChanged(boolean expanded) {
         updateExpandedHeightToMaxHeight();
-        setStatusAccessibilityImportance(expanded
-                ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
-                : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
         updateSystemUiStateFlags();
         NavigationBarView navigationBarView =
                 mNavigationBarController.getNavigationBarView(mDisplayId);
@@ -4243,7 +3376,6 @@
         mKeyguardStatusBarViewController.updateViewState();
         int barState = getBarState();
         if (barState == SHADE_LOCKED || barState == KEYGUARD) {
-            updateKeyguardBottomAreaAlpha();
             positionClockAndNotifications();
         }
 
@@ -4261,23 +3393,12 @@
         }
     }
 
-    private void onQsStateUpdated(boolean qsExpanded, boolean isStackScrollerOverscrolling) {
-        if (mKeyguardUserSwitcherController != null && qsExpanded
-                && !isStackScrollerOverscrolling) {
-            mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(true);
-        }
-    }
-
     private void onQsClippingImmediatelyApplied(boolean clipStatusView,
             Rect lastQsClipBounds, int top, boolean qsFragmentCreated, boolean qsVisible) {
         if (qsFragmentCreated) {
             mKeyguardInteractor.setQuickSettingsVisible(qsVisible);
         }
 
-        // The padding on this area is large enough that
-        // we can use a cheaper clipping strategy
-        mKeyguardStatusViewController.setClipBounds(
-                clipStatusView ? lastQsClipBounds : null);
         if (mSplitShadeEnabled) {
             mKeyguardStatusBarViewController.setNoTopClipping();
         } else {
@@ -4318,9 +3439,6 @@
                     == firstRow))) {
                 requestScrollerTopPaddingUpdate(false /* animate */);
             }
-            if (isKeyguardShowing()) {
-                updateMaxDisplayedNotifications(true);
-            }
             updateExpandedHeightToMaxHeight();
         }
 
@@ -4342,7 +3460,6 @@
         public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
             if (inPinnedMode) {
                 mHeadsUpExistenceChangedRunnable.run();
-                updateNotificationTranslucency();
             } else {
                 setHeadsUpAnimatingAway(true);
                 mNotificationStackScrollLayoutController.runAfterAnimationFinished(
@@ -4383,44 +3500,12 @@
         }
 
         @Override
-        public void onSmallestScreenWidthChanged() {
-            Trace.beginSection("onSmallestScreenWidthChanged");
-            debugLog("onSmallestScreenWidthChanged");
-
-            // Can affect multi-user switcher visibility as it depends on screen size by default:
-            // it is enabled only for devices with large screens (see config_keyguardUserSwitcher)
-            boolean prevKeyguardUserSwitcherEnabled = mKeyguardUserSwitcherEnabled;
-            boolean prevKeyguardQsUserSwitchEnabled = mKeyguardQsUserSwitchEnabled;
-            updateUserSwitcherFlags();
-            if (prevKeyguardUserSwitcherEnabled != mKeyguardUserSwitcherEnabled
-                    || prevKeyguardQsUserSwitchEnabled != mKeyguardQsUserSwitchEnabled) {
-                reInflateViews();
-            }
-
-            Trace.endSection();
-        }
-
-        @Override
         public void onDensityOrFontScaleChanged() {
             debugLog("onDensityOrFontScaleChanged");
             reInflateViews();
         }
     }
 
-    private final class SettingsChangeObserver extends ContentObserver {
-        SettingsChangeObserver(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            debugLog("onSettingsChanged");
-
-            // Can affect multi-user switcher visibility
-            reInflateViews();
-        }
-    }
-
     private final class StatusBarStateListener implements StateListener {
         @Override
         public void onStateChanged(int statusBarState) {
@@ -4436,28 +3521,6 @@
             int oldState = mBarState;
             boolean keyguardShowing = statusBarState == KEYGUARD;
 
-            if (mDozeParameters.shouldDelayKeyguardShow()
-                    && oldState == StatusBarState.SHADE
-                    && statusBarState == KEYGUARD) {
-                // This means we're doing the screen off animation - position the keyguard status
-                // view where it'll be on AOD, so we can animate it in.
-                if (!MigrateClocksToBlueprint.isEnabled()) {
-                    mKeyguardStatusViewController.updatePosition(
-                            mClockPositionResult.clockX,
-                            mClockPositionResult.clockYFullyDozing,
-                            mClockPositionResult.clockScale,
-                            false /* animate */);
-                }
-            }
-
-            if (!MigrateClocksToBlueprint.isEnabled()) {
-                mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
-                        statusBarState,
-                        keyguardFadingAway,
-                        goingToFullShade,
-                        mBarState);
-            }
-
             // TODO: maybe add a listener for barstate
             mBarState = statusBarState;
             mQsController.setBarState(statusBarState);
@@ -4519,10 +3582,8 @@
                 updateDozingVisibilities(false /* animate */);
             }
 
-            updateMaxDisplayedNotifications(false);
             // The update needs to happen after the headerSlide in above, otherwise the translation
             // would reset
-            maybeAnimateBottomAreaAlpha();
             mQsController.updateQsState();
         }
 
@@ -4557,12 +3618,7 @@
     public void showAodUi() {
         setDozing(true /* dozing */, false /* animate */);
         mStatusBarStateController.setUpcomingState(KEYGUARD);
-
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mStatusBarStateController.setState(KEYGUARD);
-        } else {
-            mStatusBarStateListener.onStateChanged(KEYGUARD);
-        }
+        mStatusBarStateController.setState(KEYGUARD);
         mStatusBarStateListener.onDozeAmountChanged(1f, 1f);
         setExpandedFraction(1f);
     }
@@ -4592,12 +3648,10 @@
             mConfigurationListener.onThemeChanged();
             mFalsingManager.addTapListener(mFalsingTapListener);
             mKeyguardIndicationController.init();
-            registerSettingsChangeListener();
         }
 
         @Override
         public void onViewDetachedFromWindow(View v) {
-            mContentResolver.unregisterContentObserver(mSettingsChangeObserver);
             mFragmentService.getFragmentHostManager(mView)
                     .removeTagListener(QS.TAG, mQsController.getQsFragmentListener());
             mStatusBarStateController.removeCallback(mStatusBarStateListener);
@@ -4618,14 +3672,8 @@
                 fling(mUpdateFlingVelocity);
                 mUpdateFlingOnLayout = false;
             }
-            updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount());
             setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth());
 
-            // Update Clock Pivot (used by anti-burnin transformations)
-            if (!MigrateClocksToBlueprint.isEnabled()) {
-                mKeyguardStatusViewController.updatePivot(mView.getWidth(), mView.getHeight());
-            }
-
             int oldMaxHeight = mQsController.updateHeightsOnShadeLayoutChange();
             positionClockAndNotifications();
             mQsController.handleShadeLayoutChanged(oldMaxHeight);
@@ -4705,43 +3753,6 @@
             // Also animate the status bar's alpha during transitions between the lockscreen and
             // dreams.
             mKeyguardStatusBarViewController.setAlpha(alpha);
-            setTransitionAlpha(stackScroller).accept(alpha);
-        };
-    }
-
-    private Consumer<Float> setTransitionAlpha(
-            NotificationStackScrollLayoutController stackScroller) {
-        return setTransitionAlpha(stackScroller, /* excludeNotifications= */ false);
-    }
-
-    private Consumer<Float> setTransitionAlpha(
-            NotificationStackScrollLayoutController stackScroller,
-            boolean excludeNotifications) {
-        return (Float alpha) -> {
-            mKeyguardStatusViewController.setAlpha(alpha);
-            if (!excludeNotifications) {
-                stackScroller.setMaxAlphaForKeyguard(alpha, "NPVC.setTransitionAlpha()");
-            }
-
-            mKeyguardInteractor.setAlpha(alpha);
-
-            if (mKeyguardQsUserSwitchController != null) {
-                mKeyguardQsUserSwitchController.setAlpha(alpha);
-            }
-            if (mKeyguardUserSwitcherController != null) {
-                mKeyguardUserSwitcherController.setAlpha(alpha);
-            }
-        };
-    }
-
-    private Consumer<Float> setTransitionY(
-                NotificationStackScrollLayoutController stackScroller) {
-        return (Float translationY) -> {
-            if (!MigrateClocksToBlueprint.isEnabled()) {
-                mKeyguardStatusViewController.setTranslationY(translationY,
-                        /* excludeMedia= */false);
-                stackScroller.setTranslationY(translationY);
-            }
         };
     }
 
@@ -4769,7 +3780,7 @@
          */
         @Override
         public boolean onInterceptTouchEvent(MotionEvent event) {
-            if (MigrateClocksToBlueprint.isEnabled() && !mUseExternalTouch) {
+            if (!mUseExternalTouch) {
                 return false;
             }
 
@@ -4834,14 +3845,10 @@
             final float x = event.getX(pointerIndex);
             final float y = event.getY(pointerIndex);
             boolean canCollapsePanel = canCollapsePanelOnTouch();
-            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(event)
-                    || isTrackpadThreeFingerSwipe(event);
+            final boolean isTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(event);
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
-                    if (!MigrateClocksToBlueprint.isEnabled()) {
-                        mCentralSurfaces.userActivity();
-                    }
                     mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
                     mMinExpandHeight = 0.0f;
                     mDownTime = mSystemClock.uptimeMillis();
@@ -4853,9 +3860,6 @@
                         return true;
                     }
 
-                    mIsTrackpadReverseScroll =
-                            !mNaturalScrollingSettingObserver.isNaturalScrollingEnabled()
-                                    && isTrackpadScroll(event);
                     if (!isTracking() || isFullyCollapsed()) {
                         mInitialExpandY = y;
                         mInitialExpandX = x;
@@ -4875,7 +3879,7 @@
                     addMovement(event);
                     break;
                 case MotionEvent.ACTION_POINTER_UP:
-                    if (isTrackpadTwoOrThreeFingerSwipe) {
+                    if (isTrackpadThreeFingerSwipe) {
                         break;
                     }
                     final int upPointer = event.getPointerId(event.getActionIndex());
@@ -4891,14 +3895,14 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "onInterceptTouchEvent: pointer down action");
-                    if (!isTrackpadTwoOrThreeFingerSwipe
+                    if (!isTrackpadThreeFingerSwipe
                             && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         mVelocityTracker.clear();
                     }
                     break;
                 case MotionEvent.ACTION_MOVE:
-                    final float h = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
+                    final float h = y - mInitialExpandY;
                     addMovement(event);
                     final boolean openShadeWithoutHun =
                             mPanelClosedOnDown && !mCollapsedAndHeadsUpOnDown;
@@ -4940,7 +3944,7 @@
          */
         @Override
         public boolean onTouchEvent(MotionEvent event) {
-            if (MigrateClocksToBlueprint.isEnabled() && !mUseExternalTouch) {
+            if (!mUseExternalTouch) {
                 return false;
             }
 
@@ -5078,14 +4082,22 @@
             final float x = event.getX(pointerIndex);
             final float y = event.getY(pointerIndex);
 
-            if (event.getActionMasked() == MotionEvent.ACTION_DOWN
+            boolean isDown = event.getActionMasked() == MotionEvent.ACTION_DOWN;
+            if (isDown
                     || event.getActionMasked() == MotionEvent.ACTION_MOVE) {
                 mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
                 mIgnoreXTouchSlop = true;
             }
 
-            final boolean isTrackpadTwoOrThreeFingerSwipe = isTrackpadScroll(event)
-                    || isTrackpadThreeFingerSwipe(event);
+            final boolean isTrackpadThreeFingerSwipe = isTrackpadThreeFingerSwipe(event);
+            if (com.android.systemui.Flags.disableShadeExpandsOnTrackpadTwoFingerSwipe()
+                    && !isTrackpadThreeFingerSwipe && isTwoFingerSwipeTrackpadEvent(event)
+                    && !isPanelExpanded()) {
+                if (isDown) {
+                    mShadeLog.d("ignoring down event for two finger trackpad swipe");
+                }
+                return false;
+            }
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
@@ -5123,7 +4135,7 @@
                     break;
 
                 case MotionEvent.ACTION_POINTER_UP:
-                    if (isTrackpadTwoOrThreeFingerSwipe) {
+                    if (isTrackpadThreeFingerSwipe) {
                         break;
                     }
                     final int upPointer = event.getPointerId(event.getActionIndex());
@@ -5142,7 +4154,7 @@
                     mShadeLog.logMotionEventStatusBarState(event,
                             mStatusBarStateController.getState(),
                             "handleTouch: pointer down action");
-                    if (!isTrackpadTwoOrThreeFingerSwipe
+                    if (!isTrackpadThreeFingerSwipe
                             && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
                         mMotionAborted = true;
                         endMotionEvent(event, x, y, true /* forceCancel */);
@@ -5165,7 +4177,7 @@
                     if (!isFullyCollapsed()) {
                         maybeVibrateOnOpening(true /* openingWithTouch */);
                     }
-                    float h = (mIsTrackpadReverseScroll ? -1 : 1) * (y - mInitialExpandY);
+                    float h = y - mInitialExpandY;
 
                     // If the panel was collapsed when touching, we only need to check for the
                     // y-component of the gesture, as we have no conflicting horizontal gesture.
@@ -5175,7 +4187,9 @@
                         mTouchSlopExceeded = true;
                         if (mGestureWaitForTouchSlop
                                 && !isTracking()
-                                && !mCollapsedAndHeadsUpOnDown) {
+                                && !mCollapsedAndHeadsUpOnDown
+                                && !isTwoFingerSwipeTrackpadEvent(event)
+                        ) {
                             if (mInitialOffsetOnTouch != 0f) {
                                 startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
                                 h = 0;
@@ -5214,13 +4228,19 @@
                             mQsController.cancelJankMonitoring();
                         }
                     }
-                    mIsTrackpadReverseScroll = false;
                     break;
             }
             return !mGestureWaitForTouchSlop || isTracking();
         }
     }
 
+    private static boolean isTwoFingerSwipeTrackpadEvent(MotionEvent event) {
+        //SOURCE_MOUSE because SOURCE_TOUCHPAD is reserved for "captured" touchpads
+        return event.getSource() == InputDevice.SOURCE_MOUSE
+                && event.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER
+                && event.getClassification() == MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE;
+    }
+
     private final class HeadsUpNotificationViewControllerImpl implements
             HeadsUpTouchHelper.HeadsUpNotificationViewController {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 69b3cc8..e4cd7ea 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -27,6 +27,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -252,6 +253,19 @@
         if (mCurrentState.shadeOrQsExpanded != isExpanded) {
             mCurrentState.shadeOrQsExpanded = isExpanded;
             apply(mCurrentState);
+
+            final IBinder token;
+            if (com.android.window.flags.Flags.schedulingForNotificationShade()
+                    && (token = mWindowRootView.getWindowToken()) != null) {
+                mBackgroundExecutor.execute(() -> {
+                    try {
+                        WindowManagerGlobal.getWindowManagerService()
+                                .onNotificationShadeExpanded(token, isExpanded);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Failed to call onNotificationShadeExpanded", e);
+                    }
+                });
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index f2c3906..e5dcd23 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -23,6 +23,7 @@
 
 import android.app.StatusBarManager;
 import android.util.Log;
+import android.view.Choreographer;
 import android.view.GestureDetector;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -48,7 +49,6 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.model.Edge;
 import com.android.systemui.keyguard.shared.model.KeyguardState;
@@ -61,6 +61,7 @@
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor;
 import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround;
 import com.android.systemui.shared.animation.DisableSubpixelTextTransitionListener;
+import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationInsetsController;
@@ -80,6 +81,8 @@
 import com.android.systemui.unfold.SysUIUnfoldComponent;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.util.time.SystemClock;
+import com.android.systemui.window.ui.WindowRootViewBinder;
+import com.android.systemui.window.ui.viewmodel.WindowRootViewModel;
 
 import kotlinx.coroutines.ExperimentalCoroutinesApi;
 
@@ -161,6 +164,9 @@
     @ExperimentalCoroutinesApi
     @Inject
     public NotificationShadeWindowViewController(
+            BlurUtils blurUtils,
+            WindowRootViewModel.Factory windowRootViewModelFactory,
+            Choreographer choreographer,
             LockscreenShadeTransitionController transitionController,
             FalsingCollector falsingCollector,
             SysuiStatusBarStateController statusBarStateController,
@@ -260,9 +266,18 @@
         if (ShadeWindowGoesAround.isEnabled()) {
             mView.setConfigurationForwarder(configurationForwarder.get());
         }
+        bindWindowRootView(blurUtils, windowRootViewModelFactory, choreographer);
         dumpManager.registerDumpable(this);
     }
 
+    private void bindWindowRootView(BlurUtils blurUtils,
+            WindowRootViewModel.Factory windowRootViewModelFactory, Choreographer choreographer) {
+        if (SceneContainerFlag.isEnabled()) return;
+
+        WindowRootViewBinder.INSTANCE.bind(mView, windowRootViewModelFactory, blurUtils,
+                choreographer);
+    }
+
     private void bindBouncer(BouncerViewBinder bouncerViewBinder) {
         mBouncerParentView = mView.findViewById(R.id.keyguard_bouncer_container);
         bouncerViewBinder.bind(mBouncerParentView);
@@ -367,9 +382,7 @@
                     mTouchActive = true;
                     mTouchCancelled = false;
                     mDownEvent = ev;
-                    if (MigrateClocksToBlueprint.isEnabled()) {
-                        mService.userActivity();
-                    }
+                    mService.userActivity();
                 } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
                         || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
                     mTouchActive = false;
@@ -443,8 +456,7 @@
                     float x = ev.getRawX();
                     float y = ev.getRawY();
                     if (mStatusBarViewController.touchIsWithinView(x, y)) {
-                        if (!(MigrateClocksToBlueprint.isEnabled()
-                                && mPrimaryBouncerInteractor.isBouncerShowing())) {
+                        if (!mPrimaryBouncerInteractor.isBouncerShowing()) {
                             if (mStatusBarWindowStateController.windowIsShowing()) {
                                 mIsTrackingBarGesture = true;
                                 return logDownDispatch(ev, "sending touch to status bar",
@@ -453,7 +465,7 @@
                                 return logDownDispatch(ev, "hidden or hiding", true);
                             }
                         } else {
-                            mShadeLogger.d("NSWVC: bouncer not showing");
+                            mShadeLogger.d("NSWVC: bouncer showing");
                         }
                     } else {
                         mShadeLogger.d("NSWVC: touch not within view");
@@ -511,34 +523,24 @@
                         && !bouncerShowing
                         && !mStatusBarStateController.isDozing()) {
                     if (mDragDownHelper.isDragDownEnabled()) {
-                        if (MigrateClocksToBlueprint.isEnabled()) {
-                            // When on lockscreen, if the touch originates at the top of the screen
-                            // go directly to QS and not the shade
-                            if (mStatusBarStateController.getState() == KEYGUARD
-                                    && mQuickSettingsController.shouldQuickSettingsIntercept(
-                                        ev.getX(), ev.getY(), 0)) {
-                                mShadeLogger.d("NSWVC: QS intercepted");
-                                return true;
-                            }
+                        // When on lockscreen, if the touch originates at the top of the screen go
+                        // directly to QS and not the shade
+                        if (mStatusBarStateController.getState() == KEYGUARD
+                                && mQuickSettingsController.shouldQuickSettingsIntercept(
+                                    ev.getX(), ev.getY(), 0)) {
+                            mShadeLogger.d("NSWVC: QS intercepted");
+                            return true;
                         }
 
                         // This handles drag down over lockscreen
                         boolean result = mDragDownHelper.onInterceptTouchEvent(ev);
-                        if (MigrateClocksToBlueprint.isEnabled()) {
-                            if (result) {
-                                mLastInterceptWasDragDownHelper = true;
-                                if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-                                    mShadeLogger.d("NSWVC: drag down helper intercepted");
-                                }
-                            } else if (didNotificationPanelInterceptEvent(ev)) {
-                                return true;
+                        if (result) {
+                            mLastInterceptWasDragDownHelper = true;
+                            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                                mShadeLogger.d("NSWVC: drag down helper intercepted");
                             }
-                        } else {
-                            if (result) {
-                                if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-                                    mShadeLogger.d("NSWVC: drag down helper intercepted");
-                                }
-                            }
+                        } else if (didNotificationPanelInterceptEvent(ev)) {
+                            return true;
                         }
                         return result;
                     } else {
@@ -547,12 +549,10 @@
                             return true;
                         }
                     }
-                } else if (MigrateClocksToBlueprint.isEnabled()) {
+                } else if (!bouncerShowing && didNotificationPanelInterceptEvent(ev)) {
                     // This final check handles swipes on HUNs and when Pulsing
-                    if (!bouncerShowing && didNotificationPanelInterceptEvent(ev)) {
-                        mShadeLogger.d("NSWVC: intercepted for HUN/PULSING");
-                        return true;
-                    }
+                    mShadeLogger.d("NSWVC: intercepted for HUN/PULSING");
+                    return true;
                 }
                 return false;
             }
@@ -562,9 +562,6 @@
                 MotionEvent cancellation = MotionEvent.obtain(ev);
                 cancellation.setAction(MotionEvent.ACTION_CANCEL);
                 mStackScrollLayout.onInterceptTouchEvent(cancellation);
-                if (!MigrateClocksToBlueprint.isEnabled()) {
-                    mShadeViewController.handleExternalInterceptTouch(cancellation);
-                }
                 cancellation.recycle();
             }
 
@@ -574,22 +571,12 @@
                 if (mStatusBarStateController.isDozing()) {
                     handled = !mDozeServiceHost.isPulsing();
                 }
-                if (MigrateClocksToBlueprint.isEnabled()) {
-                    if (mLastInterceptWasDragDownHelper && (mDragDownHelper.isDraggingDown())) {
-                        // we still want to finish our drag down gesture when locking the screen
-                        handled |= mDragDownHelper.onTouchEvent(ev) || handled;
-                    }
-                    if (!handled && mShadeViewController.handleExternalTouch(ev)) {
-                        return true;
-                    }
-                } else {
-                    if (mDragDownHelper.isDragDownEnabled()
-                            || mDragDownHelper.isDraggingDown()) {
-                        // we still want to finish our drag down gesture when locking the screen
-                        return mDragDownHelper.onTouchEvent(ev) || handled;
-                    } else {
-                        return handled;
-                    }
+                if (mLastInterceptWasDragDownHelper && (mDragDownHelper.isDraggingDown())) {
+                    // we still want to finish our drag down gesture when locking the screen
+                    handled |= mDragDownHelper.onTouchEvent(ev) || handled;
+                }
+                if (!handled && mShadeViewController.handleExternalTouch(ev)) {
+                    return true;
                 }
                 return handled;
             }
@@ -673,14 +660,12 @@
     }
 
     private boolean didNotificationPanelInterceptEvent(MotionEvent ev) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            // Since NotificationStackScrollLayout is now a sibling of notification_panel, we need
-            // to also ask NotificationPanelViewController directly, in order to process swipe up
-            // events originating from notifications
-            if (mShadeViewController.handleExternalInterceptTouch(ev)) {
-                mShadeLogger.d("NSWVC: NPVC intercepted");
-                return true;
-            }
+        // Since NotificationStackScrollLayout is now a sibling of notification_panel, we need to
+        // also ask NotificationPanelViewController directly, in order to process swipe up events
+        // originating from notifications
+        if (mShadeViewController.handleExternalInterceptTouch(ev)) {
+            mShadeLogger.d("NSWVC: NPVC intercepted");
+            return true;
         }
 
         return false;
@@ -707,9 +692,7 @@
         if (!SceneContainerFlag.isEnabled()) {
             mAmbientState.setSwipingUp(false);
         }
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            mDragDownHelper.stopDragging();
-        }
+        mDragDownHelper.stopDragging();
     }
 
     private void setBrightnessMirrorShowingForDepth(boolean showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
index 207439e..7299f09 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
@@ -21,18 +21,15 @@
 import android.view.WindowInsets
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.widget.ConstraintSet
-import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
 import androidx.constraintlayout.widget.ConstraintSet.END
 import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import androidx.lifecycle.lifecycleScope
 import com.android.app.tracing.coroutines.launchTraced as launch
-import com.android.systemui.customization.R as customR
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.fragments.FragmentService
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.navigationbar.NavigationModeController
 import com.android.systemui.plugins.qs.QS
@@ -273,9 +270,7 @@
         ensureAllViewsHaveIds(mView)
         val constraintSet = ConstraintSet()
         constraintSet.clone(mView)
-        setKeyguardStatusViewConstraints(constraintSet)
         setQsConstraints(constraintSet)
-        setNotificationsConstraints(constraintSet)
         setLargeScreenShadeHeaderConstraints(constraintSet)
         mView.applyConstraints(constraintSet)
     }
@@ -288,21 +283,6 @@
         }
     }
 
-    private fun setNotificationsConstraints(constraintSet: ConstraintSet) {
-        if (MigrateClocksToBlueprint.isEnabled) {
-            return
-        }
-        val startConstraintId = if (splitShadeEnabled) R.id.qs_edge_guideline else PARENT_ID
-        val nsslId = R.id.notification_stack_scroller
-        constraintSet.apply {
-            connect(nsslId, START, startConstraintId, START)
-            setMargin(nsslId, START, if (splitShadeEnabled) 0 else panelMarginHorizontal)
-            setMargin(nsslId, END, panelMarginHorizontal)
-            setMargin(nsslId, TOP, topMargin)
-            setMargin(nsslId, BOTTOM, notificationsBottomMargin)
-        }
-    }
-
     private fun setQsConstraints(constraintSet: ConstraintSet) {
         val endConstraintId = if (splitShadeEnabled) R.id.qs_edge_guideline else PARENT_ID
         constraintSet.apply {
@@ -313,15 +293,6 @@
         }
     }
 
-    private fun setKeyguardStatusViewConstraints(constraintSet: ConstraintSet) {
-        val statusViewMarginHorizontal =
-            resources.getDimensionPixelSize(customR.dimen.status_view_margin_horizontal)
-        constraintSet.apply {
-            setMargin(R.id.keyguard_status_view, START, statusViewMarginHorizontal)
-            setMargin(R.id.keyguard_status_view, END, statusViewMarginHorizontal)
-        }
-    }
-
     private fun ensureAllViewsHaveIds(parentView: ViewGroup) {
         for (i in 0 until parentView.childCount) {
             val childView = parentView.getChildAt(i)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
index 1333055..000a666 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
@@ -21,7 +21,6 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
@@ -33,13 +32,10 @@
 import androidx.constraintlayout.widget.ConstraintSet;
 
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 
-import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.function.Consumer;
 
 /**
@@ -50,11 +46,7 @@
 
     private View mQsFrame;
     private View mStackScroller;
-    private View mKeyguardStatusBar;
 
-    private final ArrayList<View> mDrawingOrderedChildren = new ArrayList<>();
-    private final ArrayList<View> mLayoutDrawingOrder = new ArrayList<>();
-    private final Comparator<View> mIndexComparator = Comparator.comparingInt(this::indexOfChild);
     private Consumer<WindowInsets> mInsetsChangedListener = insets -> {};
     private Consumer<QS> mQSFragmentAttachedListener = qs -> {};
     private QS mQs;
@@ -80,7 +72,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mQsFrame = findViewById(R.id.qs_frame);
-        mKeyguardStatusBar = findViewById(R.id.keyguard_header);
     }
 
     void setStackScroller(View stackScroller) {
@@ -160,46 +151,11 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        mDrawingOrderedChildren.clear();
-        mLayoutDrawingOrder.clear();
-        if (mKeyguardStatusBar.getVisibility() == View.VISIBLE) {
-            mDrawingOrderedChildren.add(mKeyguardStatusBar);
-            mLayoutDrawingOrder.add(mKeyguardStatusBar);
-        }
-        if (mQsFrame.getVisibility() == View.VISIBLE) {
-            mDrawingOrderedChildren.add(mQsFrame);
-            mLayoutDrawingOrder.add(mQsFrame);
-        }
-        if (mStackScroller.getVisibility() == View.VISIBLE) {
-            mDrawingOrderedChildren.add(mStackScroller);
-            mLayoutDrawingOrder.add(mStackScroller);
-        }
-
-        // Let's now find the order that the view has when drawing regularly by sorting
-        mLayoutDrawingOrder.sort(mIndexComparator);
-        super.dispatchDraw(canvas);
-    }
-
-    @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         return TouchLogger.logDispatchTouch("NotificationsQuickSettingsContainer", ev,
                 super.dispatchTouchEvent(ev));
     }
 
-    @Override
-    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return super.drawChild(canvas, child, drawingTime);
-        }
-        int layoutIndex = mLayoutDrawingOrder.indexOf(child);
-        if (layoutIndex >= 0) {
-            return super.drawChild(canvas, mDrawingOrderedChildren.get(layoutIndex), drawingTime);
-        } else {
-            return super.drawChild(canvas, child, drawingTime);
-        }
-    }
-
     public void applyConstraints(ConstraintSet constraintSet) {
         constraintSet.applyTo(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
index 0df2299..c88e7b8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java
@@ -68,7 +68,6 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager;
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
 import com.android.systemui.plugins.FalsingManager;
@@ -1200,7 +1199,6 @@
                 !mSplitShadeEnabled && qsExpansionFraction == 0 && qsPanelBottomY > 0;
         final boolean qsVisible = qsExpansionFraction > 0;
         final boolean qsOrQqsVisible = qqsVisible || qsVisible;
-        checkCorrectScrimVisibility(qsExpansionFraction);
 
         int top = calculateTopClippingBound(qsPanelBottomY);
         int bottom = calculateBottomClippingBound(top);
@@ -1404,21 +1402,6 @@
         }
     }
 
-    private void checkCorrectScrimVisibility(float expansionFraction) {
-        // issues with scrims visible on keyguard occur only in split shade
-        if (mSplitShadeEnabled) {
-            // TODO (b/265193930): remove dependency on NPVC
-            boolean keyguardViewsVisible = mBarState == KEYGUARD
-                            && mPanelViewControllerLazy.get().getKeyguardOnlyContentAlpha() == 1;
-            // expansionFraction == 1 means scrims are fully visible as their size/visibility depend
-            // on QS expansion
-            if (expansionFraction == 1 && keyguardViewsVisible) {
-                Log.wtf(TAG,
-                        "Incorrect state, scrim is visible at the same time when clock is visible");
-            }
-        }
-    }
-
     @Override
     public float calculateNotificationsTopPadding(boolean isShadeExpanding,
             int keyguardNotificationStaticPadding, float expandedFraction) {
@@ -1828,16 +1811,6 @@
                             "onQsIntercept: down action, QS partially expanded/collapsed");
                     return true;
                 }
-                // TODO (b/265193930): remove dependency on NPVC
-                if (mPanelViewControllerLazy.get().isKeyguardShowing()
-                        && shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
-                    // Dragging down on the lockscreen statusbar should prohibit other interactions
-                    // immediately, otherwise we'll wait on the touchslop. This is to allow
-                    // dragging down to expanded quick settings directly on the lockscreen.
-                    if (!MigrateClocksToBlueprint.isEnabled()) {
-                        mPanelView.getParent().requestDisallowInterceptTouchEvent(true);
-                    }
-                }
                 if (mExpansionAnimator != null) {
                     mInitialHeightOnTouch = mExpansionHeight;
                     mShadeLog.logMotionEvent(event,
@@ -1879,9 +1852,6 @@
                         && Math.abs(h) > Math.abs(x - mInitialTouchX)
                         && shouldQuickSettingsIntercept(
                         mInitialTouchX, mInitialTouchY, h)) {
-                    if (!MigrateClocksToBlueprint.isEnabled()) {
-                        mPanelView.getParent().requestDisallowInterceptTouchEvent(true);
-                    }
                     mShadeLog.onQsInterceptMoveQsTrackingEnabled(h);
                     setTracking(true);
                     traceQsJank(true, false);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
index d31868c..63e8ba8 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
@@ -30,11 +30,15 @@
 import com.android.systemui.common.ui.data.repository.ConfigurationRepositoryImpl
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractorImpl
+import com.android.systemui.common.ui.view.ChoreographerUtils
+import com.android.systemui.common.ui.view.ChoreographerUtilsImpl
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.res.R
 import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.shade.data.repository.MutableShadeDisplaysRepository
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractorImpl
 import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
 import com.android.systemui.shade.data.repository.ShadeDisplaysRepositoryImpl
 import com.android.systemui.shade.display.ShadeDisplayPolicyModule
@@ -216,6 +220,25 @@
     }
 
     @Provides
+    @SysUISingleton
+    fun provideShadeDialogContextInteractor(
+        impl: ShadeDialogContextInteractorImpl
+    ): ShadeDialogContextInteractor = impl
+
+    @Provides
+    @IntoMap
+    @ClassKey(ShadeDialogContextInteractor::class)
+    fun provideShadeDialogContextInteractorCoreStartable(
+        impl: Provider<ShadeDialogContextInteractorImpl>
+    ): CoreStartable {
+        return if (ShadeWindowGoesAround.isEnabled) {
+            impl.get()
+        } else {
+            CoreStartable.NOP
+        }
+    }
+
+    @Provides
     @IntoMap
     @ClassKey(ShadePrimaryDisplayCommand::class)
     fun provideShadePrimaryDisplayCommand(
@@ -239,6 +262,12 @@
         }
     }
 
+    /**
+     * Provided for making classes easier to test. In tests, a custom method to wait for the next
+     * frame can be easily provided.
+     */
+    @Provides fun provideChoreographerUtils(): ChoreographerUtils = ChoreographerUtilsImpl
+
     @Provides
     @ShadeOnDefaultDisplayWhenLocked
     fun provideShadeOnDefaultDisplayWhenLocked(): Boolean = true
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTracker.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTracker.kt
new file mode 100644
index 0000000..4d35d0e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTracker.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shade
+
+import android.util.Log
+import android.view.Display
+import com.android.app.tracing.coroutines.TrackTracer
+import com.android.internal.util.LatencyTracker
+import com.android.systemui.common.ui.data.repository.ConfigurationRepository
+import com.android.systemui.common.ui.view.ChoreographerUtils
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.scene.ui.view.WindowRootView
+import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker.Companion.TIMEOUT
+import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
+import com.android.systemui.util.kotlin.getOrNull
+import java.util.Optional
+import java.util.concurrent.CancellationException
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeout
+
+/**
+ * Tracks the time it takes to move the shade from one display to another.
+ * - The start event is when [ShadeDisplaysRepository] propagates the new display ID.
+ * - The end event is one frame after the shade configuration controller receives a new
+ *   configuration change.
+ *
+ * Note that even in the unlikely case the configuration of the new display is the same,
+ * onConfigurationChange is called anyway as is is triggered by
+ * [NotificationShadeWindowView.onMovedToDisplay].
+ */
+@SysUISingleton
+class ShadeDisplayChangeLatencyTracker
+@Inject
+constructor(
+    optionalShadeRootView: Optional<WindowRootView>,
+    @ShadeDisplayAware private val configurationRepository: ConfigurationRepository,
+    private val latencyTracker: LatencyTracker,
+    @Background private val bgScope: CoroutineScope,
+    private val choreographerUtils: ChoreographerUtils,
+) {
+
+    private val shadeRootView =
+        optionalShadeRootView.getOrNull()
+            ?: error(
+                """
+            ShadeRootView must be provided for ShadeDisplayChangeLatencyTracker to work.
+            If it is not, it means this is being instantiated in a SystemUI variant that shouldn't.
+            """
+                    .trimIndent()
+            )
+    /**
+     * We need to keep this always up to date eagerly to avoid delays receiving the new display ID.
+     */
+    private val onMovedToDisplayFlow: StateFlow<Int> =
+        configurationRepository.onMovedToDisplay.stateIn(
+            bgScope,
+            SharingStarted.Eagerly,
+            Display.DEFAULT_DISPLAY,
+        )
+
+    private var previousJob: Job? = null
+
+    /**
+     * Called before the display change begins.
+     *
+     * It is guaranteed that context and resources are still associated to the "old" display id, and
+     * that onMovedToDisplay has not been received yet on the notification shade window root view.
+     *
+     * IMPORTANT: this shouldn't be refactored to use [ShadePositionRepository], otherwise there is
+     * no guarantees of event order (as the shade could be reparented before the event is propagated
+     * to this class, breaking the assumption that [onMovedToDisplayFlow] didn't emit with the new
+     * display id yet.
+     */
+    @Synchronized
+    fun onShadeDisplayChanging(displayId: Int) {
+        previousJob?.cancel(CancellationException("New shade move in progress"))
+        previousJob = bgScope.launch { onShadeDisplayChangingAsync(displayId) }
+    }
+
+    private suspend fun onShadeDisplayChangingAsync(displayId: Int) {
+        try {
+            latencyTracker.onActionStart(SHADE_MOVE_ACTION)
+            waitForOnMovedToDisplayDispatchedToView(displayId)
+            waitUntilNextDoFrameDone()
+            latencyTracker.onActionEnd(SHADE_MOVE_ACTION)
+        } catch (e: Exception) {
+            val reason =
+                when (e) {
+                    is CancellationException ->
+                        "Shade move cancelled as a new move is being done " +
+                            "before the previous one finished."
+
+                    else -> "Shade move cancelled."
+                }
+            Log.e(TAG, reason, e)
+            latencyTracker.onActionCancel(SHADE_MOVE_ACTION)
+        }
+    }
+
+    private suspend fun waitForOnMovedToDisplayDispatchedToView(newDisplayId: Int) {
+        t.traceAsync({ "waitForOnMovedToDisplayDispatchedToView(newDisplayId=$newDisplayId)" }) {
+            withTimeout(TIMEOUT) { onMovedToDisplayFlow.filter { it == newDisplayId }.first() }
+            t.instant { "onMovedToDisplay received with $newDisplayId" }
+        }
+    }
+
+    private suspend fun waitUntilNextDoFrameDone(): Unit =
+        t.traceAsync("waitUntilNextDoFrameDone") {
+            withTimeout(TIMEOUT) { choreographerUtils.waitUntilNextDoFrameDone(shadeRootView) }
+        }
+
+    private companion object {
+        const val TAG = "ShadeDisplayLatency"
+        val t = TrackTracer(trackName = TAG)
+        val TIMEOUT = 3.seconds
+        const val SHADE_MOVE_ACTION = LatencyTracker.ACTION_SHADE_WINDOW_DISPLAY_CHANGE
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
index 9ca23f0..6d66a7f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurface.kt
@@ -59,12 +59,6 @@
     fun setTouchAndAnimationDisabled(disabled: Boolean)
 
     /**
-     * Notify us that {@link NotificationWakeUpCoordinator} is going to play the doze wakeup
-     * animation after a delay. If so, we'll keep the clock centered until that animation starts.
-     */
-    fun setWillPlayDelayedDozeAmountAnimation(willPlay: Boolean)
-
-    /**
      * Sets the dozing state.
      *
      * @param dozing `true` when dozing.
@@ -81,9 +75,6 @@
     /** Sets the view's alpha to max. */
     fun resetAlpha()
 
-    /** @see com.android.systemui.keyguard.ScreenLifecycle.Observer.onScreenTurningOn */
-    fun onScreenTurningOn()
-
     /**
      * Called when the device's theme changes.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurfaceImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurfaceImpl.kt
index 3bbda16..110100e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeSurfaceImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeSurfaceImpl.kt
@@ -49,10 +49,6 @@
         // TODO(b/332732878): determine if still needed
     }
 
-    override fun setWillPlayDelayedDozeAmountAnimation(willPlay: Boolean) {
-        // TODO(b/322494538): determine if still needed
-    }
-
     override fun setDozing(dozing: Boolean, animate: Boolean) {
         // Do nothing
     }
@@ -69,10 +65,6 @@
         // Do nothing
     }
 
-    override fun onScreenTurningOn() {
-        // Do nothing
-    }
-
     override fun onThemeChanged() {
         // Do nothing
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt
index 4516133..a36c56e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeTraceLogger.kt
@@ -17,45 +17,35 @@
 package com.android.systemui.shade
 
 import android.content.res.Configuration
-import android.os.Trace
-import com.android.app.tracing.TraceUtils.traceAsync
+import com.android.app.tracing.coroutines.TrackTracer
 
 /**
  * Centralized logging for shade-related events to a dedicated Perfetto track.
  *
- * Used by shade components to log events to a track named [TAG]. This consolidates shade-specific
- * events into a single track for easier analysis in Perfetto, rather than scattering them across
- * various threads' logs.
+ * Used by shade components to log events to a track named [TRACK_NAME]. This consolidates
+ * shade-specific events into a single track for easier analysis in Perfetto, rather than scattering
+ * them across various threads' logs.
  */
 object ShadeTraceLogger {
-    private const val TAG = "ShadeTraceLogger"
+    private val t = TrackTracer(trackName = "ShadeTraceLogger")
 
     @JvmStatic
     fun logOnMovedToDisplay(displayId: Int, config: Configuration) {
-        if (!Trace.isEnabled()) return
-        Trace.instantForTrack(
-            Trace.TRACE_TAG_APP,
-            TAG,
-            "onMovedToDisplay(displayId=$displayId, dpi=" + config.densityDpi + ")",
-        )
+        t.instant { "onMovedToDisplay(displayId=$displayId, dpi=${config.densityDpi})" }
     }
 
     @JvmStatic
     fun logOnConfigChanged(config: Configuration) {
-        if (!Trace.isEnabled()) return
-        Trace.instantForTrack(
-            Trace.TRACE_TAG_APP,
-            TAG,
-            "onConfigurationChanged(dpi=" + config.densityDpi + ")",
-        )
+        t.instant { "onConfigurationChanged(dpi=${config.densityDpi})" }
     }
 
+    @JvmStatic
     fun logMoveShadeWindowTo(displayId: Int) {
-        if (!Trace.isEnabled()) return
-        Trace.instantForTrack(Trace.TRACE_TAG_APP, TAG, "moveShadeWindowTo(displayId=$displayId)")
+        t.instant { "moveShadeWindowTo(displayId=$displayId)" }
     }
 
+    @JvmStatic
     fun traceReparenting(r: () -> Unit) {
-        traceAsync(TAG, { "reparenting" }) { r() }
+        t.traceAsync({ "reparenting" }) { r() }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index b085aec..8790083 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -16,7 +16,6 @@
 package com.android.systemui.shade
 
 import android.view.MotionEvent
-import android.view.ViewGroup
 import com.android.systemui.power.shared.model.WakefulnessModel
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
@@ -53,10 +52,6 @@
     @Deprecated("Does nothing when scene container is enabled.")
     fun setQsScrimEnabled(qsScrimEnabled: Boolean)
 
-    /** Sets the top spacing for the ambient indicator. */
-    @Deprecated("Does nothing when scene container is enabled.")
-    fun setAmbientIndicationTop(ambientIndicationTop: Int, ambientTextVisible: Boolean)
-
     /** Updates notification panel-specific flags on [SysUiState]. */
     @Deprecated("Does nothing when scene container is enabled.") fun updateSystemUiStateFlags()
 
@@ -169,9 +164,6 @@
     /** Cancels fold to AOD transition and resets view state. */
     @Deprecated("Used by the Keyguard Fold Transition. Needs flexiglass equivalent.")
     fun cancelFoldToAodAnimation()
-
-    /** Returns the main view of the shade. */
-    @Deprecated("Not used when migrateClocksToBlueprint enabled.") val view: ViewGroup?
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
index 53617d0..2976a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewControllerEmptyImpl.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.shade
 
 import android.view.MotionEvent
-import android.view.ViewGroup
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
 import com.android.systemui.shade.domain.interactor.ShadeBackActionInteractor
 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
@@ -55,19 +54,10 @@
 
     override fun startExpandLatencyTracking() {}
 
-    override fun startBouncerPreHideAnimation() {}
-
-    override fun dozeTimeTick() {}
-
     override fun resetViews(animate: Boolean) {}
 
     override val barState: Int = 0
 
-    @Deprecated("Only supported by very old devices that will not adopt scenes.")
-    override fun closeUserSwitcherIfOpen(): Boolean {
-        return false
-    }
-
     override fun onBackPressed() {}
 
     @Deprecated("According to b/318376223, shade predictive back is not be supported.")
@@ -81,8 +71,6 @@
 
     override fun setQsScrimEnabled(qsScrimEnabled: Boolean) {}
 
-    override fun setAmbientIndicationTop(ambientIndicationTop: Int, ambientTextVisible: Boolean) {}
-
     override fun updateSystemUiStateFlags() {}
 
     override fun updateTouchableRegion() {}
@@ -91,9 +79,6 @@
 
     @Deprecated("Not supported by scenes") override fun resetViewGroupFade() {}
 
-    @Deprecated("Not supported by scenes")
-    override fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int) {}
-
     @Deprecated("Not supported by scenes") override fun setOverStretchAmount(amount: Float) {}
 
     @Deprecated("TODO(b/325072511) delete this")
@@ -153,6 +138,4 @@
     ) {}
 
     override fun cancelFoldToAodAnimation() {}
-
-    override val view: ViewGroup? = null
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeDialogContextInteractor.kt
similarity index 70%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeDialogContextInteractor.kt
index 580f617..455370c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/FakeShadeDialogContextInteractor.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.shade.domain.interactor
 
-import com.android.systemui.kosmos.Kosmos
+import android.content.Context
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+/** Fake context repository that always returns the same context. */
+class FakeShadeDialogContextInteractor(override val context: Context) :
+    ShadeDialogContextInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractor.kt
index 15ea219..faf238c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractor.kt
@@ -29,17 +29,6 @@
     /** Returns whether the shade can be collapsed. */
     fun canBeCollapsed(): Boolean
 
-    /**
-     * Close the keyguard user switcher if it is open and capable of closing.
-     *
-     * Has no effect if user switcher isn't supported, if the user switcher is already closed, or if
-     * the user switcher uses "simple" mode. The simple user switcher cannot be closed.
-     *
-     * @return true if the keyguard user switcher was open, and is now closed
-     */
-    @Deprecated("Only supported by very old devices that will not adopt scenes.")
-    fun closeUserSwitcherIfOpen(): Boolean
-
     /** Called when Back gesture has been committed (i.e. a back event has definitely occurred) */
     fun onBackPressed()
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
index f151307..884cfc10 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
@@ -49,11 +49,6 @@
         return shadeInteractor.isAnyExpanded.value && !shadeInteractor.isUserInteracting.value
     }
 
-    @Deprecated("Only supported by very old devices that will not adopt scenes.")
-    override fun closeUserSwitcherIfOpen(): Boolean {
-        return false
-    }
-
     override fun onBackPressed() {
         animateCollapseQs(false)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt
new file mode 100644
index 0000000..201dc03
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDialogContextInteractor.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade.domain.interactor
+
+import android.content.Context
+import android.util.Log
+import android.view.Display
+import android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL
+import com.android.app.tracing.coroutines.launchTraced
+import com.android.app.tracing.traceSection
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository
+import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
+import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
+import javax.inject.Inject
+import javax.inject.Provider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.filter
+
+/** Provides the correct context to show dialogs on the shade window, whenever it moves. */
+interface ShadeDialogContextInteractor {
+    /** Context usable to create dialogs on the notification shade display. */
+    val context: Context
+}
+
+@SysUISingleton
+class ShadeDialogContextInteractorImpl
+@Inject
+constructor(
+    @Main private val defaultContext: Context,
+    private val displayWindowPropertyRepository: Provider<DisplayWindowPropertiesRepository>,
+    private val shadeDisplaysRepository: ShadeDisplaysRepository,
+    @Background private val bgScope: CoroutineScope,
+) : CoreStartable, ShadeDialogContextInteractor {
+
+    override fun start() {
+        if (ShadeWindowGoesAround.isUnexpectedlyInLegacyMode()) return
+        bgScope.launchTraced(TAG) {
+            shadeDisplaysRepository.displayId
+                // No need for default display pre-warming.
+                .filter { it != Display.DEFAULT_DISPLAY }
+                .collectLatest { displayId ->
+                    // Prewarms the context in the background every time the display changes.
+                    // In this way, there will be no main thread delays when a dialog is shown.
+                    getContextOrDefault(displayId)
+                }
+        }
+    }
+
+    override val context: Context
+        get() {
+            if (!ShadeWindowGoesAround.isEnabled) {
+                return defaultContext
+            }
+            val displayId = shadeDisplaysRepository.displayId.value
+            return getContextOrDefault(displayId)
+        }
+
+    private fun getContextOrDefault(displayId: Int): Context {
+        return try {
+            traceSection({ "Getting dialog context for displayId=$displayId" }) {
+                displayWindowPropertyRepository.get().get(displayId, DIALOG_WINDOW_TYPE).context
+            }
+        } catch (e: Exception) {
+            // This can happen if the display was disconnected in the meantime.
+            Log.e(
+                TAG,
+                "Couldn't get dialog context for displayId=$displayId. Returning default one",
+                e,
+            )
+            defaultContext
+        }
+    }
+
+    private companion object {
+        const val TAG = "ShadeDialogContextRepo"
+        const val DIALOG_WINDOW_TYPE = TYPE_STATUS_BAR_SUB_PANEL
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
index 8d536ac..be561b1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
@@ -25,14 +25,13 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.scene.ui.view.WindowRootView
 import com.android.systemui.shade.ShadeDisplayAware
+import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker
 import com.android.systemui.shade.ShadeTraceLogger.logMoveShadeWindowTo
 import com.android.systemui.shade.ShadeTraceLogger.traceReparenting
 import com.android.systemui.shade.data.repository.ShadeDisplaysRepository
 import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
-import com.android.systemui.util.kotlin.getOrNull
-import java.util.Optional
+import com.android.window.flags.Flags
 import javax.inject.Inject
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CoroutineScope
@@ -43,23 +42,13 @@
 class ShadeDisplaysInteractor
 @Inject
 constructor(
-    optionalShadeRootView: Optional<WindowRootView>,
     private val shadePositionRepository: ShadeDisplaysRepository,
     @ShadeDisplayAware private val shadeContext: WindowContext,
     @Background private val bgScope: CoroutineScope,
     @Main private val mainThreadContext: CoroutineContext,
+    private val shadeDisplayChangeLatencyTracker: ShadeDisplayChangeLatencyTracker,
 ) : CoreStartable {
 
-    private val shadeRootView =
-        optionalShadeRootView.getOrNull()
-            ?: error(
-                """
-            ShadeRootView must be provided for this ShadeDisplayInteractor to work.
-            If it is not, it means this is being instantiated in a SystemUI variant that shouldn't.
-            """
-                    .trimIndent()
-            )
-
     override fun start() {
         ShadeWindowGoesAround.isUnexpectedlyInLegacyMode()
         bgScope.launchTraced(TAG) {
@@ -87,7 +76,11 @@
         }
         try {
             withContext(mainThreadContext) {
-                traceReparenting { reparentToDisplayId(id = destinationId) }
+                traceReparenting {
+                    shadeDisplayChangeLatencyTracker.onShadeDisplayChanging(destinationId)
+                    reparentToDisplayId(id = destinationId)
+                }
+                checkContextDisplayMatchesExpected(destinationId)
             }
         } catch (e: IllegalStateException) {
             Log.e(
@@ -98,6 +91,18 @@
         }
     }
 
+    private fun checkContextDisplayMatchesExpected(destinationId: Int) {
+        if (shadeContext.displayId != destinationId) {
+            Log.wtf(
+                TAG,
+                "Shade context display id doesn't match the expected one after the move. " +
+                    "actual=${shadeContext.displayId} expected=$destinationId. " +
+                    "This means something wrong happened while trying to move the shade. " +
+                    "Flag reparentWindowTokenApi=${Flags.reparentWindowTokenApi()}",
+            )
+        }
+    }
+
     @UiThread
     private fun reparentToDisplayId(id: Int) {
         traceSection({ "reparentToDisplayId(id=$id)" }) { shadeContext.reparentToDisplay(id) }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index a3f2c64..f1765e7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -79,11 +79,7 @@
      * The fraction between [0..1] (i.e., percentage) of screen width to consider the threshold
      * between "top-left" and "top-right" for the purposes of dual-shade invocation.
      *
-     * When the dual-shade is not wide, this always returns 0.5 (the top edge is evenly split). On
-     * wide layouts however, a larger fraction is returned because only the area of the system
-     * status icons is considered top-right.
-     *
-     * Note that this fraction only determines the split between the absolute left and right
+     * Note that this fraction only determines the *split* between the absolute left and right
      * directions. In RTL layouts, the "top-start" edge will resolve to "top-right", and "top-end"
      * will resolve to "top-left".
      */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
index 987c016..049589d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractor.kt
@@ -38,12 +38,6 @@
      */
     @Deprecated("Use ShadeInteractor instead") val isExpanded: Boolean
 
-    /** Called before animating Keyguard dismissal, i.e. the animation dismissing the bouncer. */
-    fun startBouncerPreHideAnimation()
-
-    /** Called once every minute while dozing. */
-    fun dozeTimeTick()
-
     /**
      * Do not let the user drag the shade up and down for the current touch session. This is
      * necessary to avoid shade expansion while/after the bouncer is dismissed.
@@ -62,13 +56,6 @@
     /** @see ViewGroupFadeHelper.reset */
     @Deprecated("Not supported by scenes") fun resetViewGroupFade()
 
-    /**
-     * Set the alpha and translationY of the keyguard elements which only show on the lockscreen,
-     * but not in shade locked / shade. This is used when dragging down to the full shade.
-     */
-    @Deprecated("Not supported by scenes")
-    fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int)
-
     /** Sets the overstretch amount in raw pixels when dragging down. */
     @Deprecated("Not supported by scenes") fun setOverStretchAmount(amount: Float)
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
index 2d7476c..14934b3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeLockscreenInteractorImpl.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.shade.domain.interactor
 
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -27,7 +28,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
-import com.android.app.tracing.coroutines.launchTraced as launch
 import kotlinx.coroutines.withContext
 
 class ShadeLockscreenInteractorImpl
@@ -54,14 +54,6 @@
     override val isExpanded
         get() = shadeInteractor.isAnyExpanded.value
 
-    override fun startBouncerPreHideAnimation() {
-        // TODO("b/324280998") Implement replacement or delete
-    }
-
-    override fun dozeTimeTick() {
-        // TODO("b/383591086") Implement replacement or delete
-    }
-
     @Deprecated("Not supported by scenes")
     override fun blockExpansionForCurrentTouch() {
         // TODO("b/324280998") Implement replacement or delete
@@ -97,11 +89,6 @@
     }
 
     @Deprecated("Not supported by scenes")
-    override fun setKeyguardTransitionProgress(keyguardAlpha: Float, keyguardTranslationY: Int) {
-        // Now handled elsewhere. Do nothing.
-    }
-
-    @Deprecated("Not supported by scenes")
     override fun setOverStretchAmount(amount: Float) {
         // Now handled elsewhere. Do nothing.
     }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt
index c838c37..edf503d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt
@@ -76,10 +76,8 @@
 
 class ShadeModeInteractorImpl
 @Inject
-constructor(
-    @Application applicationScope: CoroutineScope,
-    private val repository: ShadeRepository,
-) : ShadeModeInteractor {
+constructor(@Application applicationScope: CoroutineScope, repository: ShadeRepository) :
+    ShadeModeInteractor {
 
     override val isShadeLayoutWide: StateFlow<Boolean> = repository.isShadeLayoutWide
 
@@ -92,15 +90,7 @@
                 initialValue = determineShadeMode(isShadeLayoutWide.value),
             )
 
-    @FloatRange(from = 0.0, to = 1.0)
-    override fun getTopEdgeSplitFraction(): Float {
-        // Note: this implicitly relies on isShadeLayoutWide being hot (i.e. collected). This
-        // assumption allows us to query its value on demand (during swipe source detection) instead
-        // of running another infinite coroutine.
-        // TODO(b/338577208): Instead of being fixed at 0.8f, this should dynamically updated based
-        //  on the position of system-status icons in the status bar.
-        return if (repository.isShadeLayoutWide.value) 0.8f else 0.5f
-    }
+    @FloatRange(from = 0.0, to = 1.0) override fun getTopEdgeSplitFraction(): Float = 0.5f
 
     private fun determineShadeMode(isShadeLayoutWide: Boolean): ShadeMode {
         return when {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index d343ed5a..04bdfbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar
 
 import android.app.ActivityManager
-import android.content.res.Resources
 import android.os.SystemProperties
 import android.os.Trace
 import android.os.Trace.TRACE_TAG_APP
@@ -29,28 +28,20 @@
 import android.view.ViewRootImpl
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.Dumpable
-import com.android.systemui.res.R
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import java.io.PrintWriter
 import javax.inject.Inject
-import com.android.systemui.Flags.notificationShadeBlur
+import com.android.systemui.keyguard.ui.transitions.BlurConfig
 
 @SysUISingleton
 open class BlurUtils @Inject constructor(
-    @Main private val resources: Resources,
+    blurConfig: BlurConfig,
     private val crossWindowBlurListeners: CrossWindowBlurListeners,
     dumpManager: DumpManager
 ) : Dumpable {
-    val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius)
-    val maxBlurRadius =
-        if (notificationShadeBlur()) {
-            resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius)
-        } else {
-            resources.getDimensionPixelSize(R.dimen.max_window_blur_radius)
-        }
-
+    val minBlurRadius = blurConfig.minBlurRadiusPx
+    val maxBlurRadius = blurConfig.maxBlurRadiusPx
 
     private var lastAppliedBlur = 0
     private var earlyWakeupEnabled = false
@@ -66,7 +57,7 @@
         if (ratio == 0f) {
             return 0f
         }
-        return MathUtils.lerp(minBlurRadius.toFloat(), maxBlurRadius.toFloat(), ratio)
+        return MathUtils.lerp(minBlurRadius, maxBlurRadius, ratio)
     }
 
     /**
@@ -76,7 +67,7 @@
         if (blur == 0f) {
             return 0f
         }
-        return MathUtils.map(minBlurRadius.toFloat(), maxBlurRadius.toFloat(),
+        return MathUtils.map(minBlurRadius, maxBlurRadius,
                 0f /* maxStart */, 1f /* maxStop */, blur)
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
index 72f2aa5a..31e5df9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
@@ -17,14 +17,19 @@
 class LockscreenShadeKeyguardTransitionController
 @AssistedInject
 constructor(
-        private val mediaHierarchyManager: MediaHierarchyManager,
-        @Assisted private val shadeLockscreenInteractor: ShadeLockscreenInteractor,
-        context: Context,
-        configurationController: ConfigurationController,
-        dumpManager: DumpManager,
-        splitShadeStateController: SplitShadeStateController
-) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager,
-        splitShadeStateController) {
+    private val mediaHierarchyManager: MediaHierarchyManager,
+    @Assisted private val shadeLockscreenInteractor: ShadeLockscreenInteractor,
+    context: Context,
+    configurationController: ConfigurationController,
+    dumpManager: DumpManager,
+    splitShadeStateController: SplitShadeStateController,
+) :
+    AbstractLockscreenShadeTransitionController(
+        context,
+        configurationController,
+        dumpManager,
+        splitShadeStateController,
+    ) {
 
     /**
      * Distance that the full shade transition takes in order for the keyguard content on
@@ -32,15 +37,6 @@
      */
     private var alphaTransitionDistance = 0
 
-    /**
-     * Distance that the full shade transition takes in order for the keyguard elements to fully
-     * translate into their final position
-     */
-    private var keyguardTransitionDistance = 0
-
-    /** The amount of vertical offset for the keyguard during the full shade transition. */
-    private var keyguardTransitionOffset = 0
-
     /** The amount of alpha that was last set on the keyguard elements. */
     private var alpha = 0f
 
@@ -50,49 +46,21 @@
     /** The amount of alpha that was last set on the keyguard status bar. */
     private var statusBarAlpha = 0f
 
-    /** The amount of translationY that was last set on the keyguard elements. */
-    private var translationY = 0
-
-    /** The latest progress [0,1] of the translationY progress. */
-    private var translationYProgress = 0f
-
     override fun updateResources() {
         alphaTransitionDistance =
             context.resources.getDimensionPixelSize(
-                R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance)
-        keyguardTransitionDistance =
-            context.resources.getDimensionPixelSize(
-                R.dimen.lockscreen_shade_keyguard_transition_distance)
-        keyguardTransitionOffset =
-            context.resources.getDimensionPixelSize(
-                R.dimen.lockscreen_shade_keyguard_transition_vertical_offset)
+                R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
+            )
     }
 
     override fun onDragDownAmountChanged(dragDownAmount: Float) {
         alphaProgress = MathUtils.saturate(dragDownAmount / alphaTransitionDistance)
         alpha = 1f - alphaProgress
-        translationY = calculateKeyguardTranslationY(dragDownAmount)
-        shadeLockscreenInteractor.setKeyguardTransitionProgress(alpha, translationY)
 
         statusBarAlpha = if (useSplitShade) alpha else -1f
         shadeLockscreenInteractor.setKeyguardStatusBarAlpha(statusBarAlpha)
     }
 
-    private fun calculateKeyguardTranslationY(dragDownAmount: Float): Int {
-        if (!useSplitShade) {
-            return 0
-        }
-        // On split-shade, the translationY of the keyguard should stay in sync with the
-        // translation of media.
-        if (mediaHierarchyManager.isCurrentlyInGuidedTransformation()) {
-            return mediaHierarchyManager.getGuidedTransformationTranslationY()
-        }
-        // When media is not showing, apply the default distance
-        translationYProgress = MathUtils.saturate(dragDownAmount / keyguardTransitionDistance)
-        val translationY = translationYProgress * keyguardTransitionOffset
-        return translationY.toInt()
-    }
-
     override fun dump(indentingPrintWriter: IndentingPrintWriter) {
         indentingPrintWriter.let {
             it.println("LockscreenShadeKeyguardTransitionController:")
@@ -100,8 +68,6 @@
             it.println("Resources:")
             it.increaseIndent()
             it.println("alphaTransitionDistance: $alphaTransitionDistance")
-            it.println("keyguardTransitionDistance: $keyguardTransitionDistance")
-            it.println("keyguardTransitionOffset: $keyguardTransitionOffset")
             it.decreaseIndent()
             it.println("State:")
             it.increaseIndent()
@@ -109,8 +75,6 @@
             it.println("alpha: $alpha")
             it.println("alphaProgress: $alphaProgress")
             it.println("statusBarAlpha: $statusBarAlpha")
-            it.println("translationProgress: $translationYProgress")
-            it.println("translationY: $translationY")
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index 1ec5357..ba41a63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -22,7 +22,6 @@
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
-import com.android.systemui.navigationbar.gestural.Utilities.isTrackpadScroll
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction
 import com.android.systemui.plugins.FalsingManager
@@ -760,7 +759,6 @@
     private var draggedFarEnough = false
     private var startingChild: ExpandableView? = null
     private var lastHeight = 0f
-    private var isTrackpadReverseScroll = false
     var isDraggingDown = false
         private set
 
@@ -798,12 +796,9 @@
                 startingChild = null
                 initialTouchY = y
                 initialTouchX = x
-                isTrackpadReverseScroll =
-                    !naturalScrollingSettingObserver.isNaturalScrollingEnabled &&
-                        isTrackpadScroll(event)
             }
             MotionEvent.ACTION_MOVE -> {
-                val h = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
+                val h = y - initialTouchY
                 // Adjust the touch slop if another gesture may be being performed.
                 val touchSlop =
                     if (event.classification == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE) {
@@ -837,7 +832,7 @@
         val y = event.y
         when (event.actionMasked) {
             MotionEvent.ACTION_MOVE -> {
-                lastHeight = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
+                lastHeight = y - initialTouchY
                 captureStartingChild(initialTouchX, initialTouchY)
                 dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
                 if (startingChild != null) {
@@ -862,14 +857,13 @@
                         !isFalseTouch &&
                         dragDownCallback.canDragDown()
                 ) {
-                    val dragDown = (if (isTrackpadReverseScroll) -1 else 1) * (y - initialTouchY)
+                    val dragDown = y - initialTouchY
                     dragDownCallback.onDraggedDown(startingChild, dragDown.toInt())
                     if (startingChild != null) {
                         expandCallback.setUserLockedChild(startingChild, false)
                         startingChild = null
                     }
                     isDraggingDown = false
-                    isTrackpadReverseScroll = false
                     shadeRepository.setLegacyLockscreenShadeTracking(false)
                     return true
                 } else {
@@ -950,7 +944,6 @@
             startingChild = null
         }
         isDraggingDown = false
-        isTrackpadReverseScroll = false
         shadeRepository.setLegacyLockscreenShadeTracking(false)
         dragDownCallback.onDragDownReset()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 3408f4f..e83cded 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -34,9 +34,9 @@
 import androidx.dynamicanimation.animation.SpringForce
 import com.android.app.animation.Interpolators
 import com.android.systemui.Dumpable
-import com.android.systemui.Flags.notificationShadeBlur
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionChangeEvent
@@ -50,10 +50,14 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.SplitShadeStateController
 import com.android.systemui.util.WallpaperController
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
+import com.android.systemui.window.flag.WindowBlurFlag
 import java.io.PrintWriter
 import javax.inject.Inject
 import kotlin.math.max
 import kotlin.math.sign
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 /**
  * Responsible for blurring the notification shade window, and applying a zoom effect to the
@@ -73,6 +77,8 @@
     private val dozeParameters: DozeParameters,
     private val context: Context,
     private val splitShadeStateController: SplitShadeStateController,
+    private val windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
+    @Application private val applicationScope: CoroutineScope,
     dumpManager: DumpManager,
     configurationController: ConfigurationController,
 ) : ShadeExpansionListener, Dumpable {
@@ -105,6 +111,8 @@
     // Only for dumpsys
     private var lastAppliedBlur = 0
 
+    val maxBlurRadiusPx = blurUtils.maxBlurRadius
+
     // Shade expansion offset that happens when pulling down on a HUN.
     var panelPullDownMinFraction = 0f
 
@@ -162,6 +170,8 @@
             shadeAnimation.finishIfRunning()
         }
 
+    private var zoomOutCalculatedFromShadeRadius: Float = 0.0f
+
     /** We're unlocking, and should not blur as the panel expansion changes. */
     var blursDisabledForUnlock: Boolean = false
         set(value) {
@@ -190,8 +200,8 @@
         val animationRadius =
             MathUtils.constrain(
                 shadeAnimation.radius,
-                blurUtils.minBlurRadius.toFloat(),
-                blurUtils.maxBlurRadius.toFloat(),
+                blurUtils.minBlurRadius,
+                blurUtils.maxBlurRadius,
             )
         val expansionRadius =
             blurUtils.blurRadiusOfRatio(
@@ -216,7 +226,7 @@
         val zoomOut = blurRadiusToZoomOut(blurRadius = shadeRadius)
         // Make blur be 0 if it is necessary to stop blur effect.
         if (scrimsVisible) {
-            if (!notificationShadeBlur()) {
+            if (!WindowBlurFlag.isEnabled) {
                 blur = 0
             }
         }
@@ -244,7 +254,7 @@
     }
 
     private val shouldBlurBeOpaque: Boolean
-        get() = if (notificationShadeBlur()) false else scrimsVisible && !blursDisabledForAppLaunch
+        get() = if (WindowBlurFlag.isEnabled) false else scrimsVisible && !blursDisabledForAppLaunch
 
     /** Callback that updates the window blur value and is called only once per frame. */
     @VisibleForTesting
@@ -363,6 +373,26 @@
                 }
             }
         )
+        initBlurListeners()
+    }
+
+    private fun initBlurListeners() {
+        if (!WindowBlurFlag.isEnabled) return
+
+        applicationScope.launch {
+            Log.d(TAG, "Starting coroutines for window root view blur")
+            windowRootViewBlurInteractor.onBlurAppliedEvent.collect { appliedBlurRadius ->
+                if (updateScheduled) {
+                    // Process the blur applied event only if we scheduled the update
+                    Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", appliedBlurRadius)
+                    updateScheduled = false
+                    onBlurApplied(appliedBlurRadius, zoomOutCalculatedFromShadeRadius)
+                } else {
+                    // Try scheduling an update now, maybe our blur request will be scheduled now.
+                    scheduleUpdate()
+                }
+            }
+        }
     }
 
     private fun updateResources() {
@@ -480,11 +510,17 @@
     }
 
     private fun scheduleUpdate() {
+        val (blur, zoomOutFromShadeRadius) = computeBlurAndZoomOut()
+        zoomOutCalculatedFromShadeRadius = zoomOutFromShadeRadius
+        if (WindowBlurFlag.isEnabled) {
+            updateScheduled =
+                windowRootViewBlurInteractor.requestBlurForShade(blur, shouldBlurBeOpaque)
+            return
+        }
         if (updateScheduled) {
             return
         }
         updateScheduled = true
-        val (blur, _) = computeBlurAndZoomOut()
         blurUtils.prepareBlur(root.viewRootImpl, blur)
         choreographer.postFrameCallback(updateBlurCallback)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index b2ca33a..a7ad462 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -44,13 +44,11 @@
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.jank.InteractionJankMonitor.Configuration;
 import com.android.internal.logging.UiEventLogger;
-import com.android.keyguard.KeyguardClockSwitch;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor;
 import com.android.systemui.deviceentry.shared.model.DeviceUnlockStatus;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -136,7 +134,6 @@
     private HistoricalState[] mHistoricalRecords = new HistoricalState[HISTORY_SIZE];
     // These views are used by InteractionJankMonitor to get callback from HWUI.
     private View mView;
-    private KeyguardClockSwitch mClockSwitchView;
 
     /**
      * If any of the system bars is hidden.
@@ -426,7 +423,6 @@
         if ((mView == null || !mView.isAttachedToWindow())
                 && (view != null && view.isAttachedToWindow())) {
             mView = view;
-            mClockSwitchView = view.findViewById(R.id.keyguard_clock_container);
         }
         mDozeAmountTarget = dozeAmount;
         if (animated) {
@@ -511,16 +507,7 @@
 
     /** Returns the id of the currently rendering clock */
     public String getClockId() {
-        if (MigrateClocksToBlueprint.isEnabled()) {
-            return mKeyguardClockInteractorLazy.get().getRenderedClockId();
-        }
-
-        if (mClockSwitchView == null) {
-            Log.e(TAG, "Clock container was missing");
-            return KeyguardClockSwitch.MISSING_CLOCK_ID;
-        }
-
-        return mClockSwitchView.getClockId();
+        return mKeyguardClockInteractorLazy.get().getRenderedClockId();
     }
 
     private void beginInteractionJankMonitor() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index 85b50d3..de08e38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -132,7 +132,7 @@
         private val phoneIcon =
             Icon.Resource(
                 com.android.internal.R.drawable.ic_phone,
-                ContentDescription.Resource(R.string.ongoing_phone_call_content_description),
+                ContentDescription.Resource(R.string.ongoing_call_content_description),
             )
         private val TAG = "CallVM".pad()
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
index b3dbf29..229cef9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/casttootherdevice/domain/interactor/MediaRouterChipInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.chips.casttootherdevice.domain.interactor
 
+import android.media.projection.StopReason
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.log.LogBuffer
@@ -65,7 +66,9 @@
 
     /** Stops the currently active MediaRouter cast. */
     fun stopCasting() {
-        activeCastDevice.value?.let { mediaRouterRepository.stopCasting(it) }
+        activeCastDevice.value?.let {
+            mediaRouterRepository.stopCasting(it, StopReason.STOP_PRIVACY_CHIP)
+        }
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index 66af275..bcd8cfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.chips.notification.ui.viewmodel
 
 import android.view.View
+import com.android.systemui.Flags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.statusbar.chips.notification.domain.interactor.StatusBarNotificationChipsInteractor
@@ -99,6 +100,17 @@
             )
         }
 
+        if (
+            Flags.promoteNotificationsAutomatically() &&
+                this.promotedContent.wasPromotedAutomatically
+        ) {
+            // When we're promoting notifications automatically, the `when` time set on the
+            // notification will likely just be set to the current time, which would cause the chip
+            // to always show "now". We don't want early testers to get that experience since it's
+            // not what will happen at launch, so just don't show any time.
+            return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
+        }
+
         if (this.promotedContent.time == null) {
             return OngoingActivityChipModel.Shown.IconOnly(icon, colors, onClickListener)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
index f5952f4..0b5e669 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/screenrecord/domain/interactor/ScreenRecordChipInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.chips.screenrecord.domain.interactor
 
+import android.media.projection.StopReason
 import com.android.systemui.Flags
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -140,7 +141,7 @@
 
     /** Stops the recording. */
     fun stopRecording() {
-        scope.launch { screenRecordRepository.stopRecording() }
+        scope.launch { screenRecordRepository.stopRecording(StopReason.STOP_PRIVACY_CHIP) }
     }
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
index 0c4c1a7..c40df98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -149,10 +149,9 @@
         // 1. Set up the right visual params.
         with(iconView) {
             id = CUSTOM_ICON_VIEW_ID
-            // TODO(b/354930838): Update the content description to not include "phone" and maybe
-            // include the app name.
+            // TODO(b/354930838): For RON chips, use the app name for the content description.
             contentDescription =
-                context.resources.getString(R.string.ongoing_phone_call_content_description)
+                context.resources.getString(R.string.ongoing_call_content_description)
             tintView(iconTint)
         }
 
@@ -349,14 +348,21 @@
         }
         // Clickable chips need to be a minimum size for accessibility purposes, but let
         // non-clickable chips be smaller.
-        if (chipModel.onClickListener != null) {
-            chipBackgroundView.minimumWidth =
+        val minimumWidth =
+            if (chipModel.onClickListener != null) {
                 chipBackgroundView.context.resources.getDimensionPixelSize(
                     R.dimen.min_clickable_item_size
                 )
-        } else {
-            chipBackgroundView.minimumWidth = 0
-        }
+            } else {
+                0
+            }
+        // The background view needs the minimum width so it only fills the area required (e.g. the
+        // 3-2-1 screen record countdown chip isn't tappable so it should have a small-width
+        // background).
+        chipBackgroundView.minimumWidth = minimumWidth
+        // The root view needs the minimum width so the second chip can hide if there isn't enough
+        // room for the chip -- see [SecondaryOngoingActivityChip].
+        chipView.minimumWidth = minimumWidth
     }
 
     @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipDateTimeView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipDateTimeView.kt
new file mode 100644
index 0000000..6ebeb84
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipDateTimeView.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.view
+
+import android.content.Context
+import android.content.res.Configuration
+import android.util.AttributeSet
+import android.widget.DateTimeView
+
+/** A [DateTimeView] for chips in the status bar. See also: [ChipTextView]. */
+class ChipDateTimeView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+    DateTimeView(context, attrs) {
+    private val textTruncationHelper = ChipTextTruncationHelper(this)
+
+    override fun onConfigurationChanged(newConfig: Configuration?) {
+        super.onConfigurationChanged(newConfig)
+        textTruncationHelper.onConfigurationChanged()
+    }
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        // Evaluate how wide the text *wants* to be if it had unlimited space. This is needed so
+        // that [textTruncationHelper.shouldShowText] works correctly.
+        super.onMeasure(textTruncationHelper.unlimitedWidthMeasureSpec.specInt, heightMeasureSpec)
+
+        if (
+            textTruncationHelper.shouldShowText(
+                desiredTextWidthPx = measuredWidth,
+                widthMeasureSpec = SysuiMeasureSpec(widthMeasureSpec),
+            )
+        ) {
+            // Show the text with the width spec specified by the helper
+            super.onMeasure(textTruncationHelper.widthMeasureSpec.specInt, heightMeasureSpec)
+        } else {
+            // Changing visibility ensures that the content description is not read aloud when the
+            // text isn't displayed.
+            visibility = GONE
+            setMeasuredDimension(0, 0)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt
new file mode 100644
index 0000000..52495eb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.view
+
+import android.view.View
+import android.view.View.MeasureSpec
+import android.widget.TextView.resolveSize
+import com.android.systemui.res.R
+
+/**
+ * Helper class to determine when a status bar chip's text should be hidden because it's too long.
+ */
+class ChipTextTruncationHelper(private val view: View) {
+    /** A measure spec for the status bar chip text with an unlimited width. */
+    val unlimitedWidthMeasureSpec =
+        SysuiMeasureSpec(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
+
+    /** The [MeasureSpec] that the view should actually use win [onMeasure]. */
+    lateinit var widthMeasureSpec: SysuiMeasureSpec
+
+    private var maxWidth: Int = 0
+        set(value) {
+            field = value
+            maximumWidthMeasureSpec =
+                SysuiMeasureSpec(MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST))
+        }
+
+    /** A measure spec for the status bar chip text with the correct maximum width. */
+    private lateinit var maximumWidthMeasureSpec: SysuiMeasureSpec
+
+    init {
+        maxWidth = fetchMaxWidth()
+    }
+
+    fun onConfigurationChanged() {
+        maxWidth = fetchMaxWidth()
+    }
+
+    /**
+     * Returns true if this view should show the text because there's enough room for a substantial
+     * amount of text, and returns false if this view should hide the text because the text is much
+     * too long.
+     *
+     * @param desiredTextWidthPx should be calculated by having the view measure itself with
+     *   [unlimitedWidthMeasureSpec] and then sending its `measuredWidth` to this method. (This
+     *   class can't compute [desiredTextWidthPx] directly because [View.onMeasure] can only be
+     *   called by the view itself.)
+     * @param widthMeasureSpec the view's current and unmodified width spec
+     */
+    fun shouldShowText(desiredTextWidthPx: Int, widthMeasureSpec: SysuiMeasureSpec): Boolean {
+        // Evaluate how wide the text *can* be based on:
+        // #1: The maximum width encoded by [maxWidth]
+        val maxWidthBasedOnDimension =
+            resolveSize(desiredTextWidthPx, maximumWidthMeasureSpec.specInt)
+        // #2: The width the view is allowed to take up (If there's 2 chips, the second chip likely
+        // has < [maxWidth] room available)
+        val maxWidthBasedOnViewSpaceAvailable =
+            resolveSize(desiredTextWidthPx, widthMeasureSpec.specInt)
+
+        val enforcedTextWidth: Int
+        if (maxWidthBasedOnViewSpaceAvailable < maxWidthBasedOnDimension) {
+            // View space available takes priority
+            this.widthMeasureSpec = widthMeasureSpec
+            enforcedTextWidth = maxWidthBasedOnViewSpaceAvailable
+        } else {
+            // Enforce the maximum width
+            this.widthMeasureSpec = maximumWidthMeasureSpec
+            enforcedTextWidth = maxWidthBasedOnDimension
+        }
+
+        // Only show the text if at least 50% of it can show. (Assume that if < 50% of the text will
+        // be visible, the text will be more confusing than helpful.)
+        return desiredTextWidthPx <= enforcedTextWidth * 2
+    }
+
+    private fun fetchMaxWidth() =
+        view.context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_max_text_width)
+}
+
+/** A typed class for [MeasureSpec] ints. */
+data class SysuiMeasureSpec(val specInt: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextView.kt
new file mode 100644
index 0000000..3bcc9c1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextView.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.view
+
+import android.content.Context
+import android.content.res.Configuration
+import android.util.AttributeSet
+import android.widget.TextView
+
+/** A [TextView] for chips in the status bar. See also: [ChipDateTimeView]. */
+class ChipTextView
+@JvmOverloads
+constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0) :
+    TextView(context, attrs, defStyle) {
+    private val textTruncationHelper = ChipTextTruncationHelper(this)
+
+    override fun onConfigurationChanged(newConfig: Configuration?) {
+        super.onConfigurationChanged(newConfig)
+        textTruncationHelper.onConfigurationChanged()
+    }
+
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        // Evaluate how wide the text *wants* to be if it had unlimited space. This is needed so
+        // that [textTruncationHelper.shouldShowText] works correctly.
+        super.onMeasure(textTruncationHelper.unlimitedWidthMeasureSpec.specInt, heightMeasureSpec)
+
+        if (
+            textTruncationHelper.shouldShowText(
+                desiredTextWidthPx = measuredWidth,
+                widthMeasureSpec = SysuiMeasureSpec(widthMeasureSpec),
+            )
+        ) {
+            // Show the text with the width spec specified by the helper
+            super.onMeasure(textTruncationHelper.widthMeasureSpec.specInt, heightMeasureSpec)
+        } else {
+            // Changing visibility ensures that the content description is not read aloud when the
+            // text isn't displayed.
+            visibility = GONE
+            setMeasuredDimension(0, 0)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt
new file mode 100644
index 0000000..f790dc9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/SecondaryOngoingActivityChip.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+/**
+ * A custom class for the secondary ongoing activity chip. This class will completely hide itself if
+ * there isn't enough room for the mimimum size chip.
+ *
+ * [this.minimumWidth] must be set correctly in order for this class to work.
+ */
+class SecondaryOngoingActivityChip(context: Context, attrs: AttributeSet) :
+    FrameLayout(context, attrs) {
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+        if (measuredWidth < this.minimumWidth) {
+            // There isn't enough room to fit even the minimum content required, so hide completely.
+            // Changing visibility ensures that the content description is not read aloud.
+            visibility = GONE
+            setMeasuredDimension(0, 0)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandParser.kt b/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandParser.kt
index de369c3..4289dab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandParser.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandParser.kt
@@ -74,7 +74,8 @@
      */
     fun parse(args: List<String>): Boolean {
         if (args.isEmpty()) {
-            return false
+            // An empty args list might be valid here if there are no required inputs
+            return validateRequiredParams()
         }
 
         val iterator = args.listIterator()
@@ -268,11 +269,7 @@
         _subCommands.add(new)
     }
 
-    internal fun flag(
-        longName: String,
-        shortName: String? = null,
-        description: String = "",
-    ): Flag {
+    internal fun flag(longName: String, shortName: String? = null, description: String = ""): Flag {
         checkCliNames(shortName, longName)?.let {
             throw IllegalArgumentException("Detected reused flag name ($it)")
         }
@@ -305,9 +302,7 @@
         return param
     }
 
-    internal fun <T : ParseableCommand> subCommand(
-        command: T,
-    ): OptionalSubCommand<T> {
+    internal fun <T : ParseableCommand> subCommand(command: T): OptionalSubCommand<T> {
         checkCliNames(null, command.name)?.let {
             throw IllegalArgumentException("Cannot re-use name for subcommand ($it)")
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 7df7ef1..254b792 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -63,6 +63,7 @@
 import com.android.systemui.statusbar.phone.ui.StatusBarIconControllerImpl;
 import com.android.systemui.statusbar.phone.ui.StatusBarIconList;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.wm.shell.shared.ShellTransitions;
 
 import dagger.Binds;
 import dagger.Lazy;
@@ -214,8 +215,8 @@
     @Provides
     @SysUISingleton
     static ActivityTransitionAnimator provideActivityTransitionAnimator(
-            @Main Executor mainExecutor) {
-        return new ActivityTransitionAnimator(mainExecutor);
+            @Main Executor mainExecutor, ShellTransitions shellTransitions) {
+        return new ActivityTransitionAnimator(mainExecutor, shellTransitions);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractor.kt
new file mode 100644
index 0000000..85c67f5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractor.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.featurepods.media.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.media.controls.data.repository.MediaFilterRepository
+import com.android.systemui.media.controls.shared.model.MediaCommonModel
+import com.android.systemui.media.controls.shared.model.MediaData
+import com.android.systemui.statusbar.featurepods.media.shared.model.MediaControlChipModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Interactor for managing the state of the media control chip in the status bar.
+ *
+ * Provides a [StateFlow] of [MediaControlChipModel] representing the current state of the media
+ * control chip. Emits a new [MediaControlChipModel] when there is an active media session and the
+ * corresponding user preference is found, otherwise emits null.
+ */
+@SysUISingleton
+class MediaControlChipInteractor
+@Inject
+constructor(
+    @Background private val applicationScope: CoroutineScope,
+    mediaFilterRepository: MediaFilterRepository,
+) {
+    private val currentMediaControls: StateFlow<List<MediaCommonModel.MediaControl>> =
+        mediaFilterRepository.currentMedia
+            .map { mediaList -> mediaList.filterIsInstance<MediaCommonModel.MediaControl>() }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = emptyList(),
+            )
+
+    /** The currently active [MediaControlChipModel] */
+    val mediaControlModel: StateFlow<MediaControlChipModel?> =
+        combine(currentMediaControls, mediaFilterRepository.selectedUserEntries) {
+                mediaControls,
+                userEntries ->
+                mediaControls
+                    .mapNotNull { userEntries[it.mediaLoadedModel.instanceId] }
+                    .firstOrNull { it.active }
+                    ?.toMediaControlChipModel()
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = null,
+            )
+}
+
+private fun MediaData.toMediaControlChipModel(): MediaControlChipModel {
+    return MediaControlChipModel(appIcon = this.appIcon, appName = this.app, songName = this.song)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/shared/model/MediaControlChipModel.kt
similarity index 67%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/shared/model/MediaControlChipModel.kt
index 580f617..4035667 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/shared/model/MediaControlChipModel.kt
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.statusbar.featurepods.media.shared.model
 
-import com.android.systemui.kosmos.Kosmos
+import android.graphics.drawable.Icon
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+/** Model used to display a media control chip in the status bar. */
+data class MediaControlChipModel(
+    val appIcon: Icon?,
+    val appName: String?,
+    val songName: CharSequence?,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7a59f79..4b4e0d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -32,7 +32,6 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.shade.ShadeExpansionChangeEvent
 import com.android.systemui.shade.ShadeExpansionListener
-import com.android.systemui.shade.ShadeViewController
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
@@ -44,11 +43,8 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.phone.KeyguardBypassController.OnBypassStateChangedListener
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.util.doOnEnd
-import com.android.systemui.util.doOnStart
 import java.io.PrintWriter
 import javax.inject.Inject
-import kotlin.math.max
 import kotlin.math.min
 import kotlinx.coroutines.CoroutineScope
 
@@ -77,8 +73,6 @@
 
     private var inputLinearDozeAmount: Float = 0.0f
     private var inputEasedDozeAmount: Float = 0.0f
-    private var delayedDozeAmountOverride: Float = 0.0f
-    private var delayedDozeAmountAnimator: ObjectAnimator? = null
     /** Valid values: {1f, 0f, null} null => use input */
     private var hardDozeAmountOverride: Float? = null
     private var hardDozeAmountOverrideSource: String = "n/a"
@@ -100,8 +94,9 @@
     var fullyAwake: Boolean = false
 
     var wakingUp = false
-        private set(value) {
+        set(value) {
             field = value
+            logger.logSetWakingUp(value)
             willWakeUp = false
             if (value) {
                 if (
@@ -342,8 +337,7 @@
 
     private fun updateDozeAmount() {
         // Calculate new doze amount (linear)
-        val newOutputLinearDozeAmount =
-            hardDozeAmountOverride ?: max(inputLinearDozeAmount, delayedDozeAmountOverride)
+        val newOutputLinearDozeAmount = hardDozeAmountOverride ?: inputLinearDozeAmount
         val changed = outputLinearDozeAmount != newOutputLinearDozeAmount
 
         // notify when the animation is starting
@@ -361,7 +355,6 @@
         outputEasedDozeAmount = dozeAmountInterpolator.getInterpolation(outputLinearDozeAmount)
         logger.logUpdateDozeAmount(
             inputLinear = inputLinearDozeAmount,
-            delayLinear = delayedDozeAmountOverride,
             hardOverride = hardDozeAmountOverride,
             outputLinear = outputLinearDozeAmount,
             state = statusBarStateController.state,
@@ -379,48 +372,6 @@
         }
     }
 
-    /**
-     * Notifies the wakeup coordinator that we're waking up.
-     *
-     * [requestDelayedAnimation] is used to request that we delay the start of the wakeup animation
-     * in order to wait for a potential fingerprint authentication to arrive, since unlocking during
-     * the wakeup animation looks chaotic.
-     *
-     * If called with [wakingUp] and [requestDelayedAnimation] both `true`, the [WakeUpListener]s
-     * are guaranteed to receive at least one [WakeUpListener.onDelayedDozeAmountAnimationRunning]
-     * call with `false` at some point in the near future. A call with `true` before that will
-     * happen if the animation is not already running.
-     */
-    fun setWakingUp(wakingUp: Boolean, requestDelayedAnimation: Boolean) {
-        logger.logSetWakingUp(wakingUp, requestDelayedAnimation)
-        this.wakingUp = wakingUp
-        if (wakingUp && requestDelayedAnimation) {
-            scheduleDelayedDozeAmountAnimation()
-        }
-    }
-
-    @Deprecated("As part of b/301915812")
-    private fun scheduleDelayedDozeAmountAnimation() {
-        val alreadyRunning = delayedDozeAmountAnimator != null
-        logger.logStartDelayedDozeAmountAnimation(alreadyRunning)
-        if (alreadyRunning) return
-        delayedDozeAmount.setValue(this, 1.0f)
-        delayedDozeAmountAnimator =
-            ObjectAnimator.ofFloat(this, delayedDozeAmount, 0.0f).apply {
-                interpolator = InterpolatorsAndroidX.LINEAR
-                duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP.toLong()
-                startDelay = ShadeViewController.WAKEUP_ANIMATION_DELAY_MS.toLong()
-                doOnStart {
-                    wakeUpListeners.forEach { it.onDelayedDozeAmountAnimationRunning(true) }
-                }
-                doOnEnd {
-                    delayedDozeAmountAnimator = null
-                    wakeUpListeners.forEach { it.onDelayedDozeAmountAnimationRunning(false) }
-                }
-                start()
-            }
-    }
-
     override fun onStateChanged(newState: Int) {
         logger.logOnStateChanged(newState = newState, storedState = state)
         if (state == StatusBarState.SHADE && newState == StatusBarState.SHADE) {
@@ -646,7 +597,6 @@
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.println("inputLinearDozeAmount: $inputLinearDozeAmount")
         pw.println("inputEasedDozeAmount: $inputEasedDozeAmount")
-        pw.println("delayedDozeAmountOverride: $delayedDozeAmountOverride")
         pw.println("hardDozeAmountOverride: $hardDozeAmountOverride")
         pw.println("hardDozeAmountOverrideSource: $hardDozeAmountOverrideSource")
         pw.println("outputLinearDozeAmount: $outputLinearDozeAmount")
@@ -667,20 +617,10 @@
         pw.println("canShowPulsingHuns: $canShowPulsingHuns")
     }
 
-    fun logDelayingClockWakeUpAnimation(delayingAnimation: Boolean) {
-        logger.logDelayingClockWakeUpAnimation(delayingAnimation)
-    }
-
     interface WakeUpListener {
         /** Called whenever the notifications are fully hidden or shown */
         fun onFullyHiddenChanged(isFullyHidden: Boolean) {}
 
-        /**
-         * Called when the animator started by [scheduleDelayedDozeAmountAnimation] begins running
-         * after the start delay, or after it ends/is cancelled.
-         */
-        fun onDelayedDozeAmountAnimationRunning(running: Boolean) {}
-
         /** Called whenever a pulse has started or stopped expanding. */
         fun onPulseExpandingChanged(isPulseExpanding: Boolean) {}
     }
@@ -697,19 +637,5 @@
                     return coordinator.linearVisibilityAmount
                 }
             }
-
-        private val delayedDozeAmount =
-            object : FloatProperty<NotificationWakeUpCoordinator>("delayedDozeAmount") {
-
-                override fun setValue(coordinator: NotificationWakeUpCoordinator, value: Float) {
-                    coordinator.delayedDozeAmountOverride = value
-                    coordinator.logger.logSetDelayDozeAmountOverride(value)
-                    coordinator.updateDozeAmount()
-                }
-
-                override fun get(coordinator: NotificationWakeUpCoordinator): Float {
-                    return coordinator.delayedDozeAmountOverride
-                }
-            }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 752ec2d..38d013c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -24,18 +24,15 @@
 constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
     private var allowThrottle = true
     private var lastSetDozeAmountLogInputWasFractional = false
-    private var lastSetDozeAmountLogDelayWasFractional = false
     private var lastSetDozeAmountLogState = -1
     private var lastSetHardOverride: Float? = null
     private var lastOnDozeAmountChangedLogWasFractional = false
-    private var lastSetDelayDozeAmountOverrideLogWasFractional = false
     private var lastSetVisibilityAmountLogWasFractional = false
     private var lastSetHideAmountLogWasFractional = false
     private var lastSetHideAmount = -1f
 
     fun logUpdateDozeAmount(
         inputLinear: Float,
-        delayLinear: Float,
         hardOverride: Float?,
         outputLinear: Float,
         state: Int,
@@ -43,11 +40,9 @@
     ) {
         // Avoid logging on every frame of the animation if important values are not changing
         val isInputFractional = inputLinear != 1f && inputLinear != 0f
-        val isDelayFractional = delayLinear != 1f && delayLinear != 0f
         if (
-            (isInputFractional || isDelayFractional) &&
+            (isInputFractional) &&
                 lastSetDozeAmountLogInputWasFractional == isInputFractional &&
-                lastSetDozeAmountLogDelayWasFractional == isDelayFractional &&
                 lastSetDozeAmountLogState == state &&
                 lastSetHardOverride == hardOverride &&
                 allowThrottle
@@ -55,7 +50,6 @@
             return
         }
         lastSetDozeAmountLogInputWasFractional = isInputFractional
-        lastSetDozeAmountLogDelayWasFractional = isDelayFractional
         lastSetDozeAmountLogState = state
         lastSetHardOverride = hardOverride
 
@@ -66,15 +60,14 @@
                 double1 = inputLinear.toDouble()
                 str1 = hardOverride.toString()
                 str2 = outputLinear.toString()
-                str3 = delayLinear.toString()
                 int1 = state
                 bool1 = changed
             },
             {
-                "updateDozeAmount() inputLinear=$double1 delayLinear=$str3" +
+                "updateDozeAmount() inputLinear=$double1" +
                     " hardOverride=$str1 outputLinear=$str2" +
                     " state=${StatusBarState.toString(int1)} changed=$bool1"
-            }
+            },
         )
     }
 
@@ -86,7 +79,7 @@
                 bool1 = dozing
                 str1 = source
             },
-            { "setDozeAmountOverride(dozing=$bool1, source=\"$str1\")" }
+            { "setDozeAmountOverride(dozing=$bool1, source=\"$str1\")" },
         )
     }
 
@@ -106,7 +99,7 @@
                     "willRemove=$willRemove onKeyguard=$onKeyguard dozing=$dozing" +
                         " bypass=$bypass animating=$animating idleOnCommunal=$idleOnCommunal"
             },
-            { "maybeClearHardDozeAmountOverrideHidingNotifs() $str1" }
+            { "maybeClearHardDozeAmountOverrideHidingNotifs() $str1" },
         )
     }
 
@@ -122,20 +115,7 @@
                 double1 = linear.toDouble()
                 str2 = eased.toString()
             },
-            { "onDozeAmountChanged(linear=$double1, eased=$str2)" }
-        )
-    }
-
-    fun logSetDelayDozeAmountOverride(linear: Float) {
-        // Avoid logging on every frame of the animation when values are fractional
-        val isFractional = linear != 1f && linear != 0f
-        if (lastSetDelayDozeAmountOverrideLogWasFractional && isFractional && allowThrottle) return
-        lastSetDelayDozeAmountOverrideLogWasFractional = isFractional
-        buffer.log(
-            TAG,
-            DEBUG,
-            { double1 = linear.toDouble() },
-            { "setDelayDozeAmountOverride($double1)" }
+            { "onDozeAmountChanged(linear=$double1, eased=$str2)" },
         )
     }
 
@@ -158,15 +138,6 @@
         buffer.log(TAG, DEBUG, { double1 = linear.toDouble() }, { "setHideAmount($double1)" })
     }
 
-    fun logStartDelayedDozeAmountAnimation(alreadyRunning: Boolean) {
-        buffer.log(
-            TAG,
-            DEBUG,
-            { bool1 = alreadyRunning },
-            { "startDelayedDozeAmountAnimation() alreadyRunning=$bool1" }
-        )
-    }
-
     fun logOnStateChanged(newState: Int, storedState: Int) {
         buffer.log(
             TAG,
@@ -178,7 +149,7 @@
             {
                 "onStateChanged(newState=${StatusBarState.toString(int1)})" +
                     " stored=${StatusBarState.toString(int2)}"
-            }
+            },
         )
     }
 
@@ -187,7 +158,7 @@
         wasCollapsedEnoughToHide: Boolean,
         isCollapsedEnoughToHide: Boolean,
         couldShowPulsingHuns: Boolean,
-        canShowPulsingHuns: Boolean
+        canShowPulsingHuns: Boolean,
     ) {
         buffer.log(
             TAG,
@@ -203,29 +174,12 @@
                 "onPanelExpansionChanged($double1):" +
                     " collapsedEnoughToHide: $bool1 -> $bool2," +
                     " canShowPulsingHuns: $bool3 -> $bool4"
-            }
-        )
-    }
-
-    fun logSetWakingUp(wakingUp: Boolean, requestDelayedAnimation: Boolean) {
-        buffer.log(
-            TAG,
-            DEBUG,
-            {
-                bool1 = wakingUp
-                bool2 = requestDelayedAnimation
             },
-            { "setWakingUp(wakingUp=$bool1, requestDelayedAnimation=$bool2)" }
         )
     }
 
-    fun logDelayingClockWakeUpAnimation(delayingAnimation: Boolean) {
-        buffer.log(
-            TAG,
-            DEBUG,
-            { bool1 = delayingAnimation },
-            { "logDelayingClockWakeUpAnimation($bool1)" }
-        )
+    fun logSetWakingUp(wakingUp: Boolean) {
+        buffer.log(TAG, DEBUG, { bool1 = wakingUp }, { "setWakingUp(wakingUp=$bool1)" })
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 46d4560f..df0cde5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
 import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator
 import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
 import com.android.systemui.statusbar.notification.shared.PriorityPeopleSection
@@ -69,6 +70,7 @@
     dismissibilityCoordinator: DismissibilityCoordinator,
     statsLoggerCoordinator: NotificationStatsLoggerCoordinator,
     bundleCoordinator: BundleCoordinator,
+    automaticPromotionCoordinator: AutomaticPromotionCoordinator,
 ) : NotifCoordinators {
 
     private val mCoreCoordinators: MutableList<CoreCoordinator> = ArrayList()
@@ -110,6 +112,7 @@
         mCoordinators.add(preparationCoordinator)
         mCoordinators.add(remoteInputCoordinator)
         mCoordinators.add(dismissibilityCoordinator)
+        mCoordinators.add(automaticPromotionCoordinator)
 
         if (NotificationsLiveDataStoreRefactor.isEnabled) {
             mCoordinators.add(statsLoggerCoordinator)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/ReferenceCoordinatorsModule.kt
similarity index 83%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/ReferenceCoordinatorsModule.kt
index c00bb93..1829c2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/ReferenceCoordinatorsModule.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators
 import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinatorsImpl
 import com.android.systemui.statusbar.notification.collection.coordinator.SensitiveContentCoordinatorModule
+import com.android.systemui.statusbar.notification.promoted.ReferenceAutomaticPromotionModule
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -28,12 +29,12 @@
 import javax.inject.Scope
 
 @Module(subcomponents = [CoordinatorsSubcomponent::class])
-object CoordinatorsModule {
+object ReferenceCoordinatorsModule {
     @SysUISingleton
     @JvmStatic
     @Provides
     fun notifCoordinators(factory: CoordinatorsSubcomponent.Factory): NotifCoordinators =
-            factory.create().notifCoordinators
+        factory.create().notifCoordinators
 }
 
 @CoordinatorScope
@@ -47,9 +48,9 @@
     }
 }
 
-@Module(includes = [
-    SensitiveContentCoordinatorModule::class,
-])
+@Module(
+    includes = [SensitiveContentCoordinatorModule::class, ReferenceAutomaticPromotionModule::class]
+)
 abstract class InternalCoordinatorsModule {
     @Binds
     @Internal
@@ -61,7 +62,4 @@
 @Retention(AnnotationRetention.RUNTIME)
 private annotation class Internal
 
-@Scope
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-annotation class CoordinatorScope
+@Scope @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class CoordinatorScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 80e8f55..d83acf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.inflation;
 
 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
@@ -186,6 +187,9 @@
         params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
         if (AsyncHybridViewInflation.isEnabled()) {
             params.markContentViewsFreeable(FLAG_CONTENT_VIEW_SINGLE_LINE);
+            if (LockscreenOtpRedaction.isSingleLineViewEnabled()) {
+                params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
+            }
         }
         mRowContentBindStage.requestRebind(entry, null);
     }
@@ -256,10 +260,10 @@
         params.requireContentViews(FLAG_CONTENT_VIEW_EXPANDED);
         params.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
         params.setUseMinimized(isMinimized);
-        // TODO b/358403414: use the different types of redaction
-        boolean needsRedaction = inflaterParams.getRedactionType() != REDACTION_TYPE_NONE;
+        int redactionType = inflaterParams.getRedactionType();
 
-        if (needsRedaction) {
+        params.setRedactionType(redactionType);
+        if (redactionType != REDACTION_TYPE_NONE) {
             params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC);
         } else {
             params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC);
@@ -276,8 +280,8 @@
         }
 
         if (LockscreenOtpRedaction.isSingleLineViewEnabled()) {
-
-            if (inflaterParams.isChildInGroup() && needsRedaction) {
+            if (inflaterParams.isChildInGroup()
+                    && redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
                 params.requireContentViews(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
             } else {
                 params.markContentViewsFreeable(FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 8a1371f..ea48fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -41,7 +41,6 @@
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotifPipelineChoreographerModule;
 import com.android.systemui.statusbar.notification.collection.coordinator.ShadeEventCoordinator;
-import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorsModule;
 import com.android.systemui.statusbar.notification.collection.inflation.BindEventManager;
 import com.android.systemui.statusbar.notification.collection.inflation.BindEventManagerImpl;
 import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
@@ -62,6 +61,7 @@
 import com.android.systemui.statusbar.notification.domain.NotificationDomainLayerModule;
 import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor;
 import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModelModule;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.notification.icon.ConversationIconManager;
 import com.android.systemui.statusbar.notification.icon.IconManager;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
@@ -78,8 +78,7 @@
 import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl;
 import com.android.systemui.statusbar.notification.logging.dagger.NotificationsLogModule;
 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor;
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationLogger;
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationsProvider;
+import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractorImpl;
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel;
 import com.android.systemui.statusbar.notification.row.NotificationEntryProcessorFactory;
 import com.android.systemui.statusbar.notification.row.NotificationEntryProcessorFactoryLooperImpl;
@@ -92,7 +91,6 @@
 import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.policy.ZenModesCleanupStartable;
 
 import dagger.Binds;
@@ -105,15 +103,12 @@
 
 import kotlinx.coroutines.CoroutineScope;
 
-import java.util.Optional;
-
 import javax.inject.Provider;
 
 /**
  * Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
  */
 @Module(includes = {
-        CoordinatorsModule.class,
         FooterViewModelModule.class,
         KeyguardNotificationVisibilityProviderModule.class,
         NotificationDataLayerModule.class,
@@ -315,21 +310,17 @@
     @ClassKey(ZenModesCleanupStartable.class)
     CoreStartable bindsZenModesCleanup(ZenModesCleanupStartable zenModesCleanup);
 
-    /**
-     * Provides {@link
-     * com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor} if
-     * one of the relevant feature flags is enabled.
-     */
+    /** Provides the default implementation of {@link PromotedNotificationContentExtractor} if at
+     * least one of the relevant feature flags is enabled, or an implementation that always returns
+     * null if none are enabled. */
     @Provides
     @SysUISingleton
-    static Optional<PromotedNotificationContentExtractor>
-            providePromotedNotificationContentExtractor(
-                    PromotedNotificationsProvider provider, Context context,
-                    PromotedNotificationLogger logger) {
+    static PromotedNotificationContentExtractor providesPromotedNotificationContentExtractor(
+            Provider<PromotedNotificationContentExtractorImpl> implProvider) {
         if (PromotedNotificationContentModel.featureFlagEnabled()) {
-            return Optional.of(new PromotedNotificationContentExtractor(provider, context, logger));
+            return implProvider.get();
         } else {
-            return Optional.empty();
+            return (entry, recoveredBuilder) -> null;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/ReferenceNotificationsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/ReferenceNotificationsModule.kt
index 4c25129..6c2c593 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/ReferenceNotificationsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/ReferenceNotificationsModule.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification.dagger
 
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationsModule
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.ReferenceCoordinatorsModule
 import com.android.systemui.statusbar.notification.row.NotificationRowModule
 import dagger.Module
 
@@ -29,7 +29,7 @@
         [
             NotificationsModule::class,
             NotificationRowModule::class,
-            PromotedNotificationsModule::class,
+            ReferenceCoordinatorsModule::class,
         ]
 )
 object ReferenceNotificationsModule
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
index 6756077..d02e17c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpManagerImpl.java
@@ -1299,7 +1299,6 @@
         }
 
         private NotificationEntry requireEntry() {
-            /* check if */ SceneContainerFlag.isUnexpectedlyInLegacyMode();
             return Objects.requireNonNull(mEntry);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
new file mode 100644
index 0000000..3957462
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/AutomaticPromotionCoordinator.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted
+
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.Coordinator
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import javax.inject.Inject
+
+/** A coordinator that may automatically promote certain notifications. */
+interface AutomaticPromotionCoordinator : Coordinator {
+    companion object {
+        /**
+         * An extra that should be set on notifications that were automatically promoted. Used in
+         * case we want to disable certain features for only automatically promoted notifications
+         * (but not normally promoted notifications).
+         */
+        const val EXTRA_WAS_AUTOMATICALLY_PROMOTED = "android.wasAutomaticallyPromoted"
+    }
+}
+
+/** A default implementation of [AutomaticPromotionCoordinator] that doesn't promote anything. */
+@CoordinatorScope
+class EmptyAutomaticPromotionCoordinator @Inject constructor() : AutomaticPromotionCoordinator {
+    override fun attach(pipeline: NotifPipeline) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
index 863c665..df2eb08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractor.kt
@@ -29,20 +29,28 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.shade.ShadeDisplayAware
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.promoted.AutomaticPromotionCoordinator.Companion.EXTRA_WAS_AUTOMATICALLY_PROMOTED
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Companion.isPromotedForStatusBarChip
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
 import javax.inject.Inject
 
+interface PromotedNotificationContentExtractor {
+    fun extractContent(
+        entry: NotificationEntry,
+        recoveredBuilder: Notification.Builder,
+    ): PromotedNotificationContentModel?
+}
+
 @SysUISingleton
-class PromotedNotificationContentExtractor
+class PromotedNotificationContentExtractorImpl
 @Inject
 constructor(
-    private val promotedNotificationsProvider: PromotedNotificationsProvider,
     @ShadeDisplayAware private val context: Context,
     private val logger: PromotedNotificationLogger,
-) {
-    fun extractContent(
+) : PromotedNotificationContentExtractor {
+    override fun extractContent(
         entry: NotificationEntry,
         recoveredBuilder: Notification.Builder,
     ): PromotedNotificationContentModel? {
@@ -51,22 +59,25 @@
             return null
         }
 
-        if (!promotedNotificationsProvider.shouldPromote(entry)) {
-            logger.logExtractionSkipped(entry, "shouldPromote returned false")
-            return null
-        }
-
         val notification = entry.sbn.notification
         if (notification == null) {
             logger.logExtractionFailed(entry, "entry.sbn.notification is null")
             return null
         }
 
+        // The status bar chips rely on this extractor, so take them into account for promotion.
+        if (!isPromotedForStatusBarChip(notification)) {
+            logger.logExtractionSkipped(entry, "isPromotedOngoing returned false")
+            return null
+        }
+
         val contentBuilder = PromotedNotificationContentModel.Builder(entry.key)
 
         // TODO: Pitch a fit if style is unsupported or mandatory fields are missing once
         // FLAG_PROMOTED_ONGOING is set reliably and we're not testing status bar chips.
 
+        contentBuilder.wasPromotedAutomatically =
+            notification.extras.getBoolean(EXTRA_WAS_AUTOMATICALLY_PROMOTED, false)
         contentBuilder.skeletonSmallIcon = entry.icons.aodIcon?.sourceIcon
         contentBuilder.appName = notification.loadHeaderAppName(context)
         contentBuilder.subText = notification.subText()
@@ -169,5 +180,5 @@
 
 private fun ProgressStyle.extractContent(contentBuilder: PromotedNotificationContentModel.Builder) {
     // TODO: Create NotificationProgressModel.toSkeleton, or something similar.
-    contentBuilder.progress = createProgressModel(0xffffffff.toInt(), 0x00000000)
+    contentBuilder.progress = createProgressModel(0xffffffff.toInt(), 0xff000000.toInt())
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLogger.kt
index 13ad141..a43f8db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationLogger.kt
@@ -19,7 +19,6 @@
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.LogLevel.ERROR
 import com.android.systemui.log.core.LogLevel.INFO
-import com.android.systemui.log.dagger.NotificationLog
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.logKey
 import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
@@ -27,7 +26,7 @@
 
 class PromotedNotificationLogger
 @Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@PromotedNotificationLog private val buffer: LogBuffer) {
     fun logExtractionSkipped(entry: NotificationEntry, reason: String) {
         buffer.log(
             EXTRACTION_TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProvider.kt
deleted file mode 100644
index 947d9e3..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProvider.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.promoted
-
-import android.app.Notification.FLAG_PROMOTED_ONGOING
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
-import javax.inject.Inject
-
-/** A provider for making decisions on which notifications should be promoted. */
-interface PromotedNotificationsProvider {
-    /** Returns true if the given notification should be promoted and false otherwise. */
-    fun shouldPromote(entry: NotificationEntry): Boolean
-}
-
-@SysUISingleton
-open class PromotedNotificationsProviderImpl @Inject constructor() : PromotedNotificationsProvider {
-    override fun shouldPromote(entry: NotificationEntry): Boolean {
-        if (!PromotedNotificationContentModel.featureFlagEnabled()) {
-            return false
-        }
-        return (entry.sbn.notification.flags and FLAG_PROMOTED_ONGOING) != 0
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ReferenceAutomaticPromotionModule.kt
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ReferenceAutomaticPromotionModule.kt
index 4be12bd..6a9bd3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ReferenceAutomaticPromotionModule.kt
@@ -16,15 +16,15 @@
 
 package com.android.systemui.statusbar.notification.promoted
 
-import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import dagger.Binds
 import dagger.Module
 
 @Module
-abstract class PromotedNotificationsModule {
+abstract class ReferenceAutomaticPromotionModule {
     @Binds
-    @SysUISingleton
-    abstract fun bindPromotedNotificationsProvider(
-        impl: PromotedNotificationsProviderImpl
-    ): PromotedNotificationsProvider
+    @CoordinatorScope
+    abstract fun bindAutomaticPromotionCoordinator(
+        impl: EmptyAutomaticPromotionCoordinator
+    ): AutomaticPromotionCoordinator
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/domain/interactor/AODPromotedNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/domain/interactor/AODPromotedNotificationInteractor.kt
new file mode 100644
index 0000000..0f21514
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/domain/interactor/AODPromotedNotificationInteractor.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+@SysUISingleton
+class AODPromotedNotificationInteractor
+@Inject
+constructor(activeNotificationsInteractor: ActiveNotificationsInteractor) {
+    val content: Flow<PromotedNotificationContentModel?> =
+        activeNotificationsInteractor.topLevelRepresentativeNotifications.map { notifs ->
+            notifs.firstNotNullOfOrNull { it.promotedContent }
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
index fe2dabe..258d80c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/shared/model/PromotedNotificationContentModel.kt
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.notification.promoted.shared.model
 
 import android.annotation.DrawableRes
+import android.app.Notification
+import android.app.Notification.FLAG_PROMOTED_ONGOING
 import android.graphics.drawable.Icon
 import androidx.annotation.ColorInt
 import com.android.internal.widget.NotificationProgressModel
@@ -28,9 +30,13 @@
  * like the skeleton view on AOD or the status bar chip.
  */
 data class PromotedNotificationContentModel(
-    val key: String,
+    val identity: Identity,
 
     // for all styles:
+    /**
+     * True if this notification was automatically promoted - see [AutomaticPromotionCoordinator].
+     */
+    val wasPromotedAutomatically: Boolean,
     val skeletonSmallIcon: Icon?, // TODO(b/377568176): Make into an IconModel.
     val appName: CharSequence?,
     val subText: CharSequence?,
@@ -58,6 +64,7 @@
     val progress: NotificationProgressModel?,
 ) {
     class Builder(val key: String) {
+        var wasPromotedAutomatically: Boolean = false
         var skeletonSmallIcon: Icon? = null
         var appName: CharSequence? = null
         var subText: CharSequence? = null
@@ -82,7 +89,8 @@
 
         fun build() =
             PromotedNotificationContentModel(
-                key = key,
+                identity = Identity(key, style),
+                wasPromotedAutomatically = wasPromotedAutomatically,
                 skeletonSmallIcon = skeletonSmallIcon,
                 appName = appName,
                 subText = subText,
@@ -103,6 +111,8 @@
             )
     }
 
+    data class Identity(val key: String, val style: Style)
+
     /** The timestamp associated with a notification, along with the mode used to display it. */
     data class When(val time: Long, val mode: Mode) {
         /** The mode used to display a notification's `when` value. */
@@ -132,5 +142,18 @@
         @JvmStatic
         fun featureFlagEnabled(): Boolean =
             PromotedNotificationUi.isEnabled || StatusBarNotifChips.isEnabled
+
+        /**
+         * Returns true if the given notification should be considered promoted when deciding
+         * whether or not to show the status bar chip UI.
+         */
+        fun isPromotedForStatusBarChip(notification: Notification): Boolean {
+            // Notification.isPromotedOngoing checks the ui_rich_ongoing flag, but we want the
+            // status bar chip to be ready before all the features behind the ui_rich_ongoing flag
+            // are ready.
+            val isPromotedForStatusBarChip =
+                StatusBarNotifChips.isEnabled && (notification.flags and FLAG_PROMOTED_ONGOING) != 0
+            return notification.isPromotedOngoing() || isPromotedForStatusBarChip
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/AODPromotedNotificationViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/AODPromotedNotificationViewModel.kt
new file mode 100644
index 0000000..adfa6a1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/AODPromotedNotificationViewModel.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.promoted.domain.interactor.AODPromotedNotificationInteractor
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Identity
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+
+@SysUISingleton
+class AODPromotedNotificationViewModel
+@Inject
+constructor(interactor: AODPromotedNotificationInteractor) {
+    private val content: Flow<PromotedNotificationContentModel?> = interactor.content
+    private val identity: Flow<Identity?> = content.mapNonNullsKeepingNulls { it.identity }
+
+    val notification: Flow<PromotedNotificationViewModel?> =
+        identity.distinctUntilChanged().mapNonNullsKeepingNulls { identity ->
+            val updates = interactor.content.filterNotNull().filter { it.identity == identity }
+            PromotedNotificationViewModel(identity, updates)
+        }
+}
+
+private fun <T, R> Flow<T?>.mapNonNullsKeepingNulls(block: (T) -> R): Flow<R?> = map {
+    it?.let(block)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/PromotedNotificationViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/PromotedNotificationViewModel.kt
new file mode 100644
index 0000000..f265e0f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/promoted/ui/viewmodel/PromotedNotificationViewModel.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted.ui.viewmodel
+
+import android.graphics.drawable.Icon
+import com.android.internal.widget.NotificationProgressModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.Style
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel.When
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+class PromotedNotificationViewModel(
+    identity: PromotedNotificationContentModel.Identity,
+    content: Flow<PromotedNotificationContentModel>,
+) {
+    // for all styles:
+
+    val key: String = identity.key
+    val style: Style = identity.style
+
+    val skeletonSmallIcon: Flow<Icon?> = content.map { it.skeletonSmallIcon }
+    val appName: Flow<CharSequence?> = content.map { it.appName }
+    val subText: Flow<CharSequence?> = content.map { it.subText }
+
+    private val time: Flow<When?> = content.map { it.time }
+    val whenTime: Flow<Long?> = time.map { it?.time }
+    val whenMode: Flow<When.Mode?> = time.map { it?.mode }
+
+    val lastAudiblyAlertedMs: Flow<Long> = content.map { it.lastAudiblyAlertedMs }
+    val profileBadgeResId: Flow<Int?> = content.map { it.profileBadgeResId }
+    val title: Flow<CharSequence?> = content.map { it.title }
+    val text: Flow<CharSequence?> = content.map { it.text }
+    val skeletonLargeIcon: Flow<Icon?> = content.map { it.skeletonLargeIcon }
+
+    // for CallStyle:
+    val personIcon: Flow<Icon?> = content.map { it.personIcon }
+    val personName: Flow<CharSequence?> = content.map { it.personName }
+    val verificationIcon: Flow<Icon?> = content.map { it.verificationIcon }
+    val verificationText: Flow<CharSequence?> = content.map { it.verificationText }
+
+    // for ProgressStyle:
+    val progress: Flow<NotificationProgressModel?> = content.map { it.progress }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 6e05e8e..70e27a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT;
 import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
 import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_EXPANDED;
 import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
@@ -25,6 +26,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Notification;
+import android.app.Notification.MessagingStyle;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.ApplicationInfo;
@@ -161,9 +163,7 @@
                 entry,
                 mConversationProcessor,
                 row,
-                bindParams.isMinimized,
-                bindParams.usesIncreasedHeight,
-                bindParams.usesIncreasedHeadsUpHeight,
+                bindParams,
                 callback,
                 mRemoteInputManager.getRemoteViewsOnClickHandler(),
                 /* isMediaFlagEnabled = */ mIsMediaInQS,
@@ -187,13 +187,13 @@
             boolean inflateSynchronously,
             @InflationFlag int reInflateFlags,
             Notification.Builder builder,
+            Context systemUiContext,
             Context packageContext,
             SmartReplyStateInflater smartRepliesInflater) {
         InflationProgress result = createRemoteViews(reInflateFlags,
                 builder,
-                bindParams.isMinimized,
-                bindParams.usesIncreasedHeight,
-                bindParams.usesIncreasedHeadsUpHeight,
+                bindParams,
+                systemUiContext,
                 packageContext,
                 row,
                 mNotifLayoutInflaterFactoryProvider,
@@ -203,18 +203,20 @@
         result = inflateSmartReplyViews(result, reInflateFlags, entry, row.getContext(),
                 packageContext, row.getExistingSmartReplyState(), smartRepliesInflater, mLogger);
         boolean isConversation = entry.getRanking().isConversation();
+        Notification.MessagingStyle messagingStyle = null;
+        if (isConversation && (AsyncHybridViewInflation.isEnabled()
+                || LockscreenOtpRedaction.isSingleLineViewEnabled())) {
+            messagingStyle = mConversationProcessor
+                    .processNotification(entry, builder, mLogger);
+        }
         if (AsyncHybridViewInflation.isEnabled()) {
-            Notification.MessagingStyle messagingStyle = null;
-            if (isConversation) {
-                messagingStyle = mConversationProcessor
-                        .processNotification(entry, builder, mLogger);
-            }
             SingleLineViewModel viewModel = SingleLineViewInflater
                     .inflateSingleLineViewModel(
                             entry.getSbn().getNotification(),
                             messagingStyle,
                             builder,
-                            row.getContext()
+                            row.getContext(),
+                            false
                     );
             // If the messagingStyle is null, we want to inflate the normal view
             isConversation = viewModel.isConversation();
@@ -228,11 +230,22 @@
                             mLogger
                     );
         }
-
         if (LockscreenOtpRedaction.isSingleLineViewEnabled()) {
-            result.mPublicInflatedSingleLineViewModel =
-                    SingleLineViewInflater.inflateRedactedSingleLineViewModel(row.getContext(),
-                            isConversation);
+            if (bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
+                result.mPublicInflatedSingleLineViewModel =
+                        SingleLineViewInflater.inflateSingleLineViewModel(
+                                entry.getSbn().getNotification(),
+                                messagingStyle,
+                                builder,
+                                row.getContext(),
+                                true);
+            } else {
+                result.mPublicInflatedSingleLineViewModel =
+                        SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+                                row.getContext(),
+                                isConversation
+                        );
+            }
             result.mPublicInflatedSingleLineView =
                     SingleLineViewInflater.inflatePublicSingleLineView(
                             isConversation,
@@ -411,8 +424,8 @@
     }
 
     private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags,
-            Notification.Builder builder, boolean isMinimized, boolean usesIncreasedHeight,
-            boolean usesIncreasedHeadsUpHeight, Context packageContext,
+            Notification.Builder builder, BindParams bindParams, Context systemUiContext,
+            Context packageContext,
             ExpandableNotificationRow row,
             NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider,
             HeadsUpStyleProvider headsUpStyleProvider,
@@ -423,13 +436,13 @@
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
                 logger.logAsyncTaskProgress(entryForLogging, "creating contracted remote view");
-                result.newContentView = createContentView(builder, isMinimized,
-                        usesIncreasedHeight);
+                result.newContentView = createContentView(builder, bindParams.isMinimized,
+                        bindParams.usesIncreasedHeight);
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
                 logger.logAsyncTaskProgress(entryForLogging, "creating expanded remote view");
-                result.newExpandedView = createExpandedView(builder, isMinimized);
+                result.newExpandedView = createExpandedView(builder, bindParams.isMinimized);
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
@@ -439,13 +452,20 @@
                     result.newHeadsUpView = builder.createCompactHeadsUpContentView();
                 } else {
                     result.newHeadsUpView = builder.createHeadsUpContentView(
-                            usesIncreasedHeadsUpHeight);
+                            bindParams.usesIncreasedHeadsUpHeight);
                 }
             }
 
             if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
                 logger.logAsyncTaskProgress(entryForLogging, "creating public remote view");
-                result.newPublicView = builder.makePublicContentView(isMinimized);
+                if (LockscreenOtpRedaction.isEnabled()
+                        && bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
+                    result.newPublicView = createSensitiveContentMessageNotification(
+                            row.getEntry().getSbn().getNotification(), builder.getStyle(),
+                            systemUiContext, packageContext).createContentView(true);
+                } else {
+                    result.newPublicView = builder.makePublicContentView(bindParams.isMinimized);
+                }
             }
 
             if (AsyncGroupHeaderViewInflation.isEnabled()) {
@@ -473,6 +493,42 @@
         });
     }
 
+    private static Notification.Builder createSensitiveContentMessageNotification(
+            Notification original,
+            Notification.Style originalStyle,
+            Context systemUiContext,
+            Context packageContext) {
+        Notification.Builder redacted =
+                new Notification.Builder(packageContext, original.getChannelId());
+        redacted.setContentTitle(original.extras.getCharSequence(Notification.EXTRA_TITLE));
+        CharSequence redactedMessage = systemUiContext.getString(
+                R.string.redacted_notification_single_line_text
+        );
+
+        if (originalStyle instanceof MessagingStyle oldStyle) {
+            MessagingStyle newStyle = new MessagingStyle(oldStyle.getUser());
+            newStyle.setConversationTitle(oldStyle.getConversationTitle());
+            newStyle.setGroupConversation(false);
+            newStyle.setConversationType(oldStyle.getConversationType());
+            newStyle.setShortcutIcon(oldStyle.getShortcutIcon());
+            newStyle.setBuilder(redacted);
+            MessagingStyle.Message latestMessage =
+                    MessagingStyle.findLatestIncomingMessage(oldStyle.getMessages());
+            if (latestMessage != null) {
+                MessagingStyle.Message newMessage = new MessagingStyle.Message(redactedMessage,
+                        latestMessage.getTimestamp(), latestMessage.getSenderPerson());
+                newStyle.addMessage(newMessage);
+            }
+            redacted.setStyle(newStyle);
+        } else {
+            redacted.setContentText(redactedMessage);
+        }
+        redacted.setLargeIcon(original.getLargeIcon());
+        redacted.setSmallIcon(original.getSmallIcon());
+        return redacted;
+    }
+
+
     private static void setNotifsViewsInflaterFactory(InflationProgress result,
             ExpandableNotificationRow row,
             NotifLayoutInflaterFactory.Provider notifLayoutInflaterFactoryProvider) {
@@ -921,7 +977,7 @@
         logger.logAsyncTaskProgress(entry, "finishing");
 
         if (PromotedNotificationContentModel.featureFlagEnabled()) {
-            entry.setPromotedNotificationContentModel(result.mExtractedPromotedNotificationContent);
+            entry.setPromotedNotificationContentModel(result.mPromotedContent);
         }
 
         boolean setRepliesAndActions = true;
@@ -1118,10 +1174,8 @@
         private final NotificationEntry mEntry;
         private final Context mContext;
         private final boolean mInflateSynchronously;
-        private final boolean mIsMinimized;
-        private final boolean mUsesIncreasedHeight;
+        private final BindParams mBindParams;
         private final InflationCallback mCallback;
-        private final boolean mUsesIncreasedHeadsUpHeight;
         private final @InflationFlag int mReInflateFlags;
         private final NotifRemoteViewCache mRemoteViewCache;
         private final Executor mInflationExecutor;
@@ -1145,9 +1199,7 @@
                 NotificationEntry entry,
                 ConversationNotificationProcessor conversationProcessor,
                 ExpandableNotificationRow row,
-                boolean isMinimized,
-                boolean usesIncreasedHeight,
-                boolean usesIncreasedHeadsUpHeight,
+                BindParams bindParams,
                 InflationCallback callback,
                 RemoteViews.InteractionHandler remoteViewClickHandler,
                 boolean isMediaFlagEnabled,
@@ -1164,9 +1216,7 @@
             mRemoteViewCache = cache;
             mSmartRepliesInflater = smartRepliesInflater;
             mContext = mRow.getContext();
-            mIsMinimized = isMinimized;
-            mUsesIncreasedHeight = usesIncreasedHeight;
-            mUsesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight;
+            mBindParams = bindParams;
             mRemoteViewClickHandler = remoteViewClickHandler;
             mCallback = callback;
             mConversationProcessor = conversationProcessor;
@@ -1236,8 +1286,7 @@
                         mEntry, recoveredBuilder, mLogger);
             }
             InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
-                    recoveredBuilder, mIsMinimized, mUsesIncreasedHeight,
-                    mUsesIncreasedHeadsUpHeight, packageContext, mRow,
+                    recoveredBuilder, mBindParams, mContext, packageContext, mRow,
                     mNotifLayoutInflaterFactoryProvider, mHeadsUpStyleProvider, mLogger);
 
             mLogger.logAsyncTaskProgress(mEntry,
@@ -1264,7 +1313,8 @@
                                 mEntry.getSbn().getNotification(),
                                 messagingStyle,
                                 recoveredBuilder,
-                                mContext
+                                mContext,
+                                false
                         );
                 result.mInflatedSingleLineView =
                         SingleLineViewInflater.inflatePrivateSingleLineView(
@@ -1277,9 +1327,22 @@
             }
 
             if (LockscreenOtpRedaction.isSingleLineViewEnabled()) {
-                result.mPublicInflatedSingleLineViewModel =
-                        SingleLineViewInflater.inflateRedactedSingleLineViewModel(mContext,
-                                isConversation);
+                if (mBindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
+                    result.mPublicInflatedSingleLineViewModel =
+                            SingleLineViewInflater.inflateSingleLineViewModel(
+                                    mEntry.getSbn().getNotification(),
+                                    messagingStyle,
+                                    recoveredBuilder,
+                                    mContext,
+                                    true
+                            );
+                } else {
+                    result.mPublicInflatedSingleLineViewModel =
+                            SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+                                    mContext,
+                                    isConversation
+                            );
+                }
                 result.mPublicInflatedSingleLineView =
                         SingleLineViewInflater.inflatePublicSingleLineView(
                                 isConversation,
@@ -1292,10 +1355,13 @@
 
             if (PromotedNotificationContentModel.featureFlagEnabled()) {
                 mLogger.logAsyncTaskProgress(mEntry, "extracting promoted notification content");
-                result.mExtractedPromotedNotificationContent = mPromotedNotificationContentExtractor
-                        .extractContent(mEntry, recoveredBuilder);
+                final PromotedNotificationContentModel promotedContent =
+                        mPromotedNotificationContentExtractor.extractContent(mEntry,
+                                recoveredBuilder);
                 mLogger.logAsyncTaskProgress(mEntry, "extracted promoted notification content: "
-                        + result.mExtractedPromotedNotificationContent);
+                        + promotedContent);
+
+                result.mPromotedContent = promotedContent;
             }
 
             mLogger.logAsyncTaskProgress(mEntry,
@@ -1317,7 +1383,7 @@
                 mCancellationSignal = apply(
                         mInflationExecutor,
                         mInflateSynchronously,
-                        mIsMinimized,
+                        mBindParams.isMinimized,
                         result,
                         mReInflateFlags,
                         mRemoteViewCache,
@@ -1399,7 +1465,7 @@
 
     @VisibleForTesting
     static class InflationProgress {
-        PromotedNotificationContentModel mExtractedPromotedNotificationContent;
+        PromotedNotificationContentModel mPromotedContent;
 
         private RemoteViews newContentView;
         private RemoteViews newHeadsUpView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
index 07384af..1cef879 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -141,20 +143,33 @@
      */
     class BindParams {
 
+        public BindParams(boolean minimized, boolean increasedHeight,
+                boolean increasedHeadsUpHeight, int redaction) {
+            isMinimized = minimized;
+            usesIncreasedHeight = increasedHeight;
+            usesIncreasedHeadsUpHeight = increasedHeadsUpHeight;
+            redactionType = redaction;
+        }
+
         /**
          * Bind a minimized version of the content views.
          */
-        public boolean isMinimized;
+        public final boolean isMinimized;
 
         /**
          * Use increased height when binding contracted view.
          */
-        public boolean usesIncreasedHeight;
+        public final boolean usesIncreasedHeight;
 
         /**
          * Use increased height when binding heads up views.
          */
-        public boolean usesIncreasedHeadsUpHeight;
+        public final boolean usesIncreasedHeadsUpHeight;
+
+        /**
+         * Controls the type of public view to show, if a public view is requested
+         */
+        public final @RedactionType int redactionType;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
index c7d80e9..c619b17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinderImpl.kt
@@ -16,8 +16,8 @@
 package com.android.systemui.statusbar.notification.row
 
 import android.annotation.SuppressLint
-import android.app.Flags
 import android.app.Notification
+import android.app.Notification.MessagingStyle
 import android.content.Context
 import android.content.ContextWrapper
 import android.content.pm.ApplicationInfo
@@ -43,6 +43,7 @@
 import com.android.systemui.dagger.qualifiers.NotifInflation
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.InflationTask
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_SENSITIVE_CONTENT
 import com.android.systemui.statusbar.NotificationRemoteInputManager
 import com.android.systemui.statusbar.notification.ConversationNotificationProcessor
 import com.android.systemui.statusbar.notification.InflationException
@@ -143,9 +144,7 @@
                 entry,
                 conversationProcessor,
                 row,
-                bindParams.isMinimized,
-                bindParams.usesIncreasedHeight,
-                bindParams.usesIncreasedHeadsUpHeight,
+                bindParams,
                 callback,
                 remoteInputManager.remoteViewsOnClickHandler,
                 /* isMediaFlagEnabled = */ smartReplyStateInflater,
@@ -179,10 +178,8 @@
                 reInflateFlags = reInflateFlags,
                 entry = entry,
                 builder = builder,
-                isMinimized = bindParams.isMinimized,
-                usesIncreasedHeight = bindParams.usesIncreasedHeight,
-                usesIncreasedHeadsUpHeight = bindParams.usesIncreasedHeadsUpHeight,
-                systemUIContext = systemUIContext,
+                bindParams,
+                systemUiContext = systemUIContext,
                 packageContext = packageContext,
                 row = row,
                 notifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider,
@@ -371,9 +368,7 @@
         private val entry: NotificationEntry,
         private val conversationProcessor: ConversationNotificationProcessor,
         private val row: ExpandableNotificationRow,
-        private val isMinimized: Boolean,
-        private val usesIncreasedHeight: Boolean,
-        private val usesIncreasedHeadsUpHeight: Boolean,
+        private val bindParams: BindParams,
         private val callback: InflationCallback?,
         private val remoteViewClickHandler: InteractionHandler?,
         private val smartRepliesInflater: SmartReplyStateInflater,
@@ -441,10 +436,8 @@
                     reInflateFlags = reInflateFlags,
                     entry = entry,
                     builder = recoveredBuilder,
-                    isMinimized = isMinimized,
-                    usesIncreasedHeight = usesIncreasedHeight,
-                    usesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight,
-                    systemUIContext = context,
+                    bindParams = bindParams,
+                    systemUiContext = context,
                     packageContext = packageContext,
                     row = row,
                     notifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider,
@@ -514,7 +507,7 @@
                         apply(
                             inflationExecutor,
                             inflateSynchronously,
-                            isMinimized,
+                            bindParams.isMinimized,
                             progress,
                             reInflateFlags,
                             remoteViewCache,
@@ -591,7 +584,7 @@
         @VisibleForTesting val packageContext: Context,
         val remoteViews: NewRemoteViews,
         val contentModel: NotificationContentModel,
-        val extractedPromotedNotificationContentModel: PromotedNotificationContentModel?,
+        val promotedContent: PromotedNotificationContentModel?,
     ) {
 
         var inflatedContentView: View? = null
@@ -671,10 +664,8 @@
             @InflationFlag reInflateFlags: Int,
             entry: NotificationEntry,
             builder: Notification.Builder,
-            isMinimized: Boolean,
-            usesIncreasedHeight: Boolean,
-            usesIncreasedHeadsUpHeight: Boolean,
-            systemUIContext: Context,
+            bindParams: BindParams,
+            systemUiContext: Context,
             packageContext: Context,
             row: ExpandableNotificationRow,
             notifLayoutInflaterFactoryProvider: NotifLayoutInflaterFactory.Provider,
@@ -683,16 +674,15 @@
             promotedNotificationContentExtractor: PromotedNotificationContentExtractor,
             logger: NotificationRowContentBinderLogger,
         ): InflationProgress {
-            val promoted =
+            val promotedContent =
                 if (PromotedNotificationContentModel.featureFlagEnabled()) {
                     logger.logAsyncTaskProgress(entry, "extracting promoted notification content")
-                    val extracted =
-                        promotedNotificationContentExtractor.extractContent(entry, builder)
-                    logger.logAsyncTaskProgress(
-                        entry,
-                        "extracted promoted notification content: {extracted}",
-                    )
-                    extracted
+                    promotedNotificationContentExtractor.extractContent(entry, builder).also {
+                        logger.logAsyncTaskProgress(
+                            entry,
+                            "extracted promoted notification content: $it",
+                        )
+                    }
                 } else {
                     null
                 }
@@ -707,9 +697,10 @@
                 createRemoteViews(
                     reInflateFlags = reInflateFlags,
                     builder = builder,
-                    isMinimized = isMinimized,
-                    usesIncreasedHeight = usesIncreasedHeight,
-                    usesIncreasedHeadsUpHeight = usesIncreasedHeadsUpHeight,
+                    bindParams = bindParams,
+                    entry = entry,
+                    systemUiContext = systemUiContext,
+                    packageContext = packageContext,
                     row = row,
                     notifLayoutInflaterFactoryProvider = notifLayoutInflaterFactoryProvider,
                     headsUpStyleProvider = headsUpStyleProvider,
@@ -726,7 +717,8 @@
                         notification = entry.sbn.notification,
                         messagingStyle = messagingStyle,
                         builder = builder,
-                        systemUiContext = systemUIContext,
+                        systemUiContext = systemUiContext,
+                        redactText = false,
                     )
                 } else null
 
@@ -736,10 +728,20 @@
                         reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC_SINGLE_LINE != 0
                 ) {
                     logger.logAsyncTaskProgress(entry, "inflating public single line view model")
-                    SingleLineViewInflater.inflateRedactedSingleLineViewModel(
-                        systemUIContext,
-                        entry.ranking.isConversation,
-                    )
+                    if (bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT) {
+                        SingleLineViewInflater.inflateSingleLineViewModel(
+                            notification = entry.sbn.notification,
+                            messagingStyle = messagingStyle,
+                            builder = builder,
+                            systemUiContext = systemUiContext,
+                            redactText = true,
+                        )
+                    } else {
+                        SingleLineViewInflater.inflateRedactedSingleLineViewModel(
+                            systemUiContext,
+                            entry.ranking.isConversation,
+                        )
+                    }
                 } else null
 
             val headsUpStatusBarModel =
@@ -759,16 +761,54 @@
                 packageContext = packageContext,
                 remoteViews = remoteViews,
                 contentModel = contentModel,
-                extractedPromotedNotificationContentModel = promoted,
+                promotedContent = promotedContent,
             )
         }
 
+        private fun createSensitiveContentMessageNotification(
+            original: Notification,
+            originalStyle: Notification.Style?,
+            sysUiContext: Context,
+            packageContext: Context,
+        ): Notification.Builder {
+            val redacted = Notification.Builder(packageContext, original.channelId)
+            redacted.setContentTitle(original.extras.getCharSequence(Notification.EXTRA_TITLE))
+            val redactedMessage =
+                sysUiContext.getString(R.string.redacted_notification_single_line_text)
+
+            if (originalStyle is MessagingStyle) {
+                val newStyle = MessagingStyle(originalStyle.user)
+                newStyle.conversationTitle = originalStyle.conversationTitle
+                newStyle.isGroupConversation = false
+                newStyle.conversationType = originalStyle.conversationType
+                newStyle.shortcutIcon = originalStyle.shortcutIcon
+                newStyle.setBuilder(redacted)
+                val latestMessage = MessagingStyle.findLatestIncomingMessage(originalStyle.messages)
+                if (latestMessage != null) {
+                    val newMessage =
+                        MessagingStyle.Message(
+                            redactedMessage,
+                            latestMessage.timestamp,
+                            latestMessage.senderPerson,
+                        )
+                    newStyle.addMessage(newMessage)
+                }
+                redacted.style = newStyle
+            } else {
+                redacted.setContentText(redactedMessage)
+            }
+            redacted.setLargeIcon(original.getLargeIcon())
+            redacted.setSmallIcon(original.smallIcon)
+            return redacted
+        }
+
         private fun createRemoteViews(
             @InflationFlag reInflateFlags: Int,
             builder: Notification.Builder,
-            isMinimized: Boolean,
-            usesIncreasedHeight: Boolean,
-            usesIncreasedHeadsUpHeight: Boolean,
+            bindParams: BindParams,
+            entry: NotificationEntry,
+            systemUiContext: Context,
+            packageContext: Context,
             row: ExpandableNotificationRow,
             notifLayoutInflaterFactoryProvider: NotifLayoutInflaterFactory.Provider,
             headsUpStyleProvider: HeadsUpStyleProvider,
@@ -782,7 +822,11 @@
                             entryForLogging,
                             "creating contracted remote view",
                         )
-                        createContentView(builder, isMinimized, usesIncreasedHeight)
+                        createContentView(
+                            builder,
+                            bindParams.isMinimized,
+                            bindParams.usesIncreasedHeight,
+                        )
                     } else null
                 val expanded =
                     if (reInflateFlags and FLAG_CONTENT_VIEW_EXPANDED != 0) {
@@ -790,7 +834,7 @@
                             entryForLogging,
                             "creating expanded remote view",
                         )
-                        createExpandedView(builder, isMinimized)
+                        createExpandedView(builder, bindParams.isMinimized)
                     } else null
                 val headsUp =
                     if (reInflateFlags and FLAG_CONTENT_VIEW_HEADS_UP != 0) {
@@ -802,13 +846,26 @@
                         if (isHeadsUpCompact) {
                             builder.createCompactHeadsUpContentView()
                         } else {
-                            builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight)
+                            builder.createHeadsUpContentView(bindParams.usesIncreasedHeadsUpHeight)
                         }
                     } else null
                 val public =
                     if (reInflateFlags and FLAG_CONTENT_VIEW_PUBLIC != 0) {
                         logger.logAsyncTaskProgress(entryForLogging, "creating public remote view")
-                        builder.makePublicContentView(isMinimized)
+                        if (
+                            LockscreenOtpRedaction.isEnabled &&
+                                bindParams.redactionType == REDACTION_TYPE_SENSITIVE_CONTENT
+                        ) {
+                            createSensitiveContentMessageNotification(
+                                    entry.sbn.notification,
+                                    builder.style,
+                                    systemUiContext,
+                                    packageContext,
+                                )
+                                .createContentView(bindParams.usesIncreasedHeight)
+                        } else {
+                            builder.makePublicContentView(bindParams.isMinimized)
+                        }
                     } else null
                 val normalGroupHeader =
                     if (
@@ -1420,8 +1477,7 @@
 
             entry.setContentModel(result.contentModel)
             if (PromotedNotificationContentModel.featureFlagEnabled()) {
-                entry.promotedNotificationContentModel =
-                    result.extractedPromotedNotificationContentModel
+                entry.promotedNotificationContentModel = result.promotedContent
             }
 
             result.inflatedSmartReplyState?.let { row.privateLayout.setInflatedSmartReplyState(it) }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
index 427fb66..bc44cb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindParams.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.REDACTION_TYPE_NONE;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.RedactionType;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
@@ -31,6 +33,7 @@
     private boolean mUseIncreasedHeadsUpHeight;
     private boolean mViewsNeedReinflation;
     private @InflationFlag int mContentViews = DEFAULT_INFLATION_FLAGS;
+    private @RedactionType int mRedactionType = REDACTION_TYPE_NONE;
 
     /**
      * Content views that are out of date and need to be rebound.
@@ -58,6 +61,20 @@
     }
 
     /**
+     * @return What type of redaction should be used by the public view (if requested)
+     */
+    public @RedactionType int getRedactionType() {
+        return mRedactionType;
+    }
+
+    /**
+     * Set the redaction type, which controls what sort of public view is shown.
+     */
+    public void setRedactionType(@RedactionType int redactionType) {
+        mRedactionType = redactionType;
+    }
+
+    /**
      * Set whether content should use an increased height version of its contracted view.
      */
     public void setUseIncreasedCollapsedHeight(boolean useIncreasedHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
index 89fcda9..53f7416 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStage.java
@@ -72,10 +72,8 @@
         // Bind/unbind with parameters
         mBinder.unbindContent(entry, row, contentToUnbind);
 
-        BindParams bindParams = new BindParams();
-        bindParams.isMinimized = params.useMinimized();
-        bindParams.usesIncreasedHeight = params.useIncreasedHeight();
-        bindParams.usesIncreasedHeadsUpHeight = params.useIncreasedHeadsUpHeight();
+        BindParams bindParams = new BindParams(params.useMinimized(), params.useIncreasedHeight(),
+                params.useIncreasedHeadsUpHeight(), params.getRedactionType());
         boolean forceInflate = params.needsReinflation();
 
         InflationCallback inflationCallback = new InflationCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index e702f10..fe2803b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -51,6 +51,7 @@
      *   notification, not for legacy messaging notifications
      * @param builder the recovered Notification Builder
      * @param systemUiContext the context of Android System UI
+     * @param redactText indicates if the text needs to be redacted
      * @return the inflated SingleLineViewModel
      */
     @JvmStatic
@@ -59,13 +60,21 @@
         messagingStyle: MessagingStyle?,
         builder: Notification.Builder,
         systemUiContext: Context,
+        redactText: Boolean,
     ): SingleLineViewModel {
         if (AsyncHybridViewInflation.isUnexpectedlyInLegacyMode()) {
             return SingleLineViewModel(null, null, null)
         }
         peopleHelper.init(systemUiContext)
         var titleText = HybridGroupManager.resolveTitle(notification)
-        var contentText = HybridGroupManager.resolveText(notification)
+        var contentText =
+            if (redactText) {
+                systemUiContext.getString(
+                    com.android.systemui.res.R.string.redacted_notification_single_line_text
+                )
+            } else {
+                HybridGroupManager.resolveText(notification)
+            }
 
         if (messagingStyle == null) {
             return SingleLineViewModel(
@@ -81,7 +90,7 @@
         if (conversationTextData?.conversationTitle?.isNotEmpty() == true) {
             titleText = conversationTextData.conversationTitle
         }
-        if (conversationTextData?.conversationText?.isNotEmpty() == true) {
+        if (!redactText && conversationTextData?.conversationText?.isNotEmpty() == true) {
             contentText = conversationTextData.conversationText
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index df43ff1..3ccf506 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import static android.app.Flags.notificationsRedesignTemplates;
 import static android.view.View.VISIBLE;
 
 import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.DEFAULT_HEADER_VISIBLE_AMOUNT;
@@ -149,10 +150,15 @@
                     }
 
                 }, TRANSFORMING_VIEW_TEXT);
-        mFullHeaderTranslation = ctx.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin)
-                - ctx.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.notification_content_margin_top);
+        int contentMargin = ctx.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_content_margin);
+        int contentMarginTop =
+                notificationsRedesignTemplates()
+                        ? Notification.Builder.getContentMarginTop(ctx,
+                            com.android.internal.R.dimen.notification_2025_content_margin_top)
+                        : ctx.getResources().getDimensionPixelSize(
+                            com.android.internal.R.dimen.notification_content_margin_top);
+        mFullHeaderTranslation = contentMargin - contentMarginTop;
     }
 
     @MainThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 00cd8ce..9fb7fad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -168,8 +168,10 @@
         mDividerHeight = res.getDimensionPixelOffset(
                 R.dimen.notification_children_container_divider_height);
         mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
-        mNotificationHeaderMargin = res.getDimensionPixelOffset(
-                R.dimen.notification_children_container_margin_top);
+        mNotificationHeaderMargin = notificationsRedesignTemplates()
+                ? Notification.Builder.getContentMarginTop(getContext(),
+                    R.dimen.notification_2025_children_container_margin_top)
+                : res.getDimensionPixelOffset(R.dimen.notification_children_container_margin_top);
         mNotificationTopPadding = res.getDimensionPixelOffset(
                 R.dimen.notification_children_container_top_padding);
         mHeaderHeight = notificationsRedesignTemplates()
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 7c9d850..38a7035 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
@@ -3729,14 +3729,6 @@
 
     // Only when scene container is enabled, mark that we are being dragged so that we start
     // dispatching the rest of the gesture to scene container.
-    void startOverscrollAfterExpanding() {
-        if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
-        getExpandHelper().finishExpanding();
-        setIsBeingDragged(true);
-    }
-
-    // Only when scene container is enabled, mark that we are being dragged so that we start
-    // dispatching the rest of the gesture to scene container.
     void startDraggingOnHun() {
         if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
         setIsBeingDragged(true);
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 245b1d2..a33a9ed 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
@@ -2203,11 +2203,10 @@
                 expandingNotification = mView.isExpandingNotification();
                 if (mView.getExpandedInThisMotion() && !expandingNotification && wasExpandingBefore
                         && !mView.getDisallowScrollingInThisMotion()) {
-                    // We need to dispatch the overscroll differently when Scene Container is on,
-                    // since NSSL no longer controls its own scroll.
+                    // Finish expansion here, as this gesture will be marked to be sent to
+                    // scene container
                     if (SceneContainerFlag.isEnabled() && !isCancelOrUp) {
-                        mView.startOverscrollAfterExpanding();
-                        return true;
+                        expandHelper.finishExpanding();
                     } else {
                         mView.dispatchDownEventToScroller(ev);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/SharedNotificationContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/SharedNotificationContainer.kt
index 42acd7bc..705845f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/SharedNotificationContainer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/SharedNotificationContainer.kt
@@ -75,7 +75,7 @@
         constraintSet.apply {
             if (SceneContainerFlag.isEnabled) {
                 when (horizontalPosition) {
-                    is HorizontalPosition.FloatAtEnd ->
+                    is HorizontalPosition.FloatAtStart ->
                         constrainWidth(nsslId, horizontalPosition.width)
                     is HorizontalPosition.MiddleToEdge ->
                         setGuidelinePercent(R.id.nssl_guideline, horizontalPosition.ratio)
@@ -83,13 +83,13 @@
                 }
             }
 
+            connect(nsslId, START, startConstraintId, START, marginStart)
             if (
                 !SceneContainerFlag.isEnabled ||
-                    horizontalPosition !is HorizontalPosition.FloatAtEnd
+                    horizontalPosition !is HorizontalPosition.FloatAtStart
             ) {
-                connect(nsslId, START, startConstraintId, START, marginStart)
+                connect(nsslId, END, PARENT_ID, END, marginEnd)
             }
-            connect(nsslId, END, PARENT_ID, END, marginEnd)
             connect(nsslId, BOTTOM, PARENT_ID, BOTTOM, marginBottom)
             connect(nsslId, TOP, PARENT_ID, TOP, marginTop)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index b81c71e..fc8c70f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -247,7 +247,7 @@
                                 Split -> HorizontalPosition.MiddleToEdge(ratio = 0.5f)
                                 Dual ->
                                     if (isShadeLayoutWide) {
-                                        HorizontalPosition.FloatAtEnd(
+                                        HorizontalPosition.FloatAtStart(
                                             width = getDimensionPixelSize(R.dimen.shade_panel_width)
                                         )
                                     } else {
@@ -830,10 +830,10 @@
         data class MiddleToEdge(val ratio: Float = 0.5f) : HorizontalPosition
 
         /**
-         * The container has a fixed [width] and is aligned to the end of the screen. In this
-         * layout, the start edge of the container is floating, i.e. unconstrained.
+         * The container has a fixed [width] and is aligned to the start of the screen. In this
+         * layout, the end edge of the container is floating, i.e. unconstrained.
          */
-        data class FloatAtEnd(val width: Int) : HorizontalPosition
+        data class FloatAtStart(val width: Int) : HorizontalPosition
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
index 86c7c6b..4751293 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -20,6 +20,7 @@
 import android.os.UserHandle
 import android.view.View
 import com.android.systemui.animation.ActivityTransitionAnimator
+import com.android.systemui.animation.TransitionAnimator
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
@@ -38,7 +39,7 @@
     private val statusBarStateController: SysuiStatusBarStateController,
     @Main private val mainExecutor: DelayableExecutor,
     activityStarterInternal: Lazy<ActivityStarterInternalImpl>,
-    legacyActivityStarter: Lazy<LegacyActivityStarterInternalImpl>
+    legacyActivityStarter: Lazy<LegacyActivityStarterInternalImpl>,
 ) : ActivityStarter {
 
     private val activityStarterInternal: ActivityStarterInternal =
@@ -48,10 +49,23 @@
             legacyActivityStarter.get()
         }
 
+    override fun registerTransition(
+        cookie: ActivityTransitionAnimator.TransitionCookie,
+        controllerFactory: ActivityTransitionAnimator.ControllerFactory,
+    ) {
+        if (!TransitionAnimator.longLivedReturnAnimationsEnabled()) return
+        activityStarterInternal.registerTransition(cookie, controllerFactory)
+    }
+
+    override fun unregisterTransition(cookie: ActivityTransitionAnimator.TransitionCookie) {
+        if (!TransitionAnimator.longLivedReturnAnimationsEnabled()) return
+        activityStarterInternal.unregisterTransition(cookie)
+    }
+
     override fun startPendingIntentDismissingKeyguard(intent: PendingIntent) {
         activityStarterInternal.startPendingIntentDismissingKeyguard(
             intent = intent,
-            dismissShade = true
+            dismissShade = true,
         )
     }
 
@@ -98,7 +112,7 @@
         intentSentUiThreadCallback: Runnable?,
         animationController: ActivityTransitionAnimator.Controller?,
         fillInIntent: Intent?,
-        extraOptions: Bundle?
+        extraOptions: Bundle?,
     ) {
         activityStarterInternal.startPendingIntentDismissingKeyguard(
             intent = intent,
@@ -115,7 +129,7 @@
     override fun startPendingIntentMaybeDismissingKeyguard(
         intent: PendingIntent,
         intentSentUiThreadCallback: Runnable?,
-        animationController: ActivityTransitionAnimator.Controller?
+        animationController: ActivityTransitionAnimator.Controller?,
     ) {
         activityStarterInternal.startPendingIntentDismissingKeyguard(
             intent = intent,
@@ -245,7 +259,7 @@
 
     override fun postStartActivityDismissingKeyguard(
         intent: PendingIntent,
-        animationController: ActivityTransitionAnimator.Controller?
+        animationController: ActivityTransitionAnimator.Controller?,
     ) {
         postOnUiThread {
             activityStarterInternal.startPendingIntentDismissingKeyguard(
@@ -381,7 +395,7 @@
         postOnUiThread {
             statusBarStateController.setLeaveOpenOnKeyguardHide(true)
             activityStarterInternal.executeRunnableDismissingKeyguard(
-                runnable = { runnable?.let { postOnUiThread(runnable = it) } },
+                runnable = { runnable?.let { postOnUiThread(runnable = it) } }
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt
index 93ce6e8..5e427fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone
 
 import android.app.PendingIntent
+import android.content.ComponentName
 import android.content.Intent
 import android.os.Bundle
 import android.os.UserHandle
@@ -27,6 +28,21 @@
 
 interface ActivityStarterInternal {
     /**
+     * Registers the given [controllerFactory] for launching and closing transitions matching the
+     * [cookie] and the [ComponentName] that it contains.
+     */
+    fun registerTransition(
+        cookie: ActivityTransitionAnimator.TransitionCookie,
+        controllerFactory: ActivityTransitionAnimator.ControllerFactory,
+    )
+
+    /**
+     * Unregisters the [ActivityTransitionAnimator.Controller] previously registered containing the
+     * given [cookie]. If no such registration exists, this is a no-op.
+     */
+    fun unregisterTransition(cookie: ActivityTransitionAnimator.TransitionCookie)
+
+    /**
      * Starts a pending intent after dismissing keyguard.
      *
      * This can be called in a background thread (to prevent calls in [ActivityIntentHelper] in the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
index f2ef2f0..33e4fed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.Flags
 import com.android.systemui.animation.ActivityTransitionAnimator
 import com.android.systemui.animation.DelegateTransitionAnimatorController
+import com.android.systemui.animation.TransitionAnimator
 import com.android.systemui.assist.AssistManager
 import com.android.systemui.camera.CameraIntents
 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
@@ -103,6 +104,44 @@
     private val centralSurfaces: CentralSurfaces?
         get() = centralSurfacesOptLazy.get().getOrNull()
 
+    override fun registerTransition(
+        cookie: ActivityTransitionAnimator.TransitionCookie,
+        controllerFactory: ActivityTransitionAnimator.ControllerFactory,
+    ) {
+        check(TransitionAnimator.longLivedReturnAnimationsEnabled())
+
+        val factory =
+            object :
+                ActivityTransitionAnimator.ControllerFactory(
+                    controllerFactory.cookie,
+                    controllerFactory.component,
+                    controllerFactory.launchCujType,
+                    controllerFactory.returnCujType,
+                ) {
+                override fun createController(
+                    forLaunch: Boolean
+                ): ActivityTransitionAnimator.Controller {
+                    val baseController = controllerFactory.createController(forLaunch)
+                    val rootView = baseController.transitionContainer.rootView
+                    val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
+                        statusBarWindowControllerStore.defaultDisplay
+                            .wrapAnimationControllerIfInStatusBar(rootView, baseController)
+                    return if (controllerFromStatusBar.isPresent) {
+                        controllerFromStatusBar.get()
+                    } else {
+                        baseController
+                    }
+                }
+            }
+
+        activityTransitionAnimator.register(cookie, factory)
+    }
+
+    override fun unregisterTransition(cookie: ActivityTransitionAnimator.TransitionCookie) {
+        check(TransitionAnimator.longLivedReturnAnimationsEnabled())
+        activityTransitionAnimator.unregister(cookie)
+    }
+
     override fun startPendingIntentDismissingKeyguard(
         intent: PendingIntent,
         dismissShade: Boolean,
@@ -134,7 +173,7 @@
                 (skipLockscreenChecks ||
                     activityIntentHelper.wouldPendingShowOverLockscreen(
                         intent,
-                        lockScreenUserManager.currentUserId
+                        lockScreenUserManager.currentUserId,
                     ))
 
         val animate =
@@ -190,7 +229,7 @@
                                 null,
                                 null,
                                 null,
-                                options.toBundle()
+                                options.toBundle(),
                             )
                         }
                     },
@@ -239,7 +278,7 @@
         animationController: ActivityTransitionAnimator.Controller?,
         customMessage: String?,
         disallowEnterPictureInPictureWhileLaunching: Boolean,
-        userHandle: UserHandle?
+        userHandle: UserHandle?,
     ) {
         if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
         val userHandle: UserHandle = userHandle ?: getActivityUserHandle(intent)
@@ -280,7 +319,7 @@
             activityTransitionAnimator.startIntentWithAnimation(
                 animController,
                 animate,
-                intent.getPackage()
+                intent.getPackage(),
             ) { adapter: RemoteAnimationAdapter? ->
                 val options =
                     ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter))
@@ -359,7 +398,7 @@
         dismissShade: Boolean,
         animationController: ActivityTransitionAnimator.Controller?,
         showOverLockscreenWhenLocked: Boolean,
-        userHandle: UserHandle?
+        userHandle: UserHandle?,
     ) {
         if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
         val userHandle = userHandle ?: getActivityUserHandle(intent)
@@ -383,7 +422,7 @@
             animationController != null &&
                 shouldAnimateLaunch(
                     isActivityIntent = true,
-                    showOverLockscreen = showOverLockscreenWhenLocked
+                    showOverLockscreen = showOverLockscreenWhenLocked,
                 )
 
         var controller: ActivityTransitionAnimator.Controller? = null
@@ -413,7 +452,7 @@
             controller,
             animate,
             intent.getPackage(),
-            showOverLockscreenWhenLocked
+            showOverLockscreenWhenLocked,
         ) { adapter: RemoteAnimationAdapter? ->
             TaskStackBuilder.create(context)
                 .addNextIntent(intent)
@@ -425,7 +464,7 @@
         action: ActivityStarter.OnDismissAction,
         cancel: Runnable?,
         afterKeyguardGone: Boolean,
-        customMessage: String?
+        customMessage: String?,
     ) {
         if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
         Log.i(TAG, "Invoking dismissKeyguardThenExecute, afterKeyguardGone: $afterKeyguardGone")
@@ -453,7 +492,7 @@
         afterKeyguardGone: Boolean,
         deferred: Boolean,
         willAnimateOnKeyguard: Boolean,
-        customMessage: String?
+        customMessage: String?,
     ) {
         if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
         val onDismissAction: ActivityStarter.OnDismissAction =
@@ -482,12 +521,7 @@
                     return willAnimateOnKeyguard
                 }
             }
-        dismissKeyguardThenExecute(
-            onDismissAction,
-            cancelAction,
-            afterKeyguardGone,
-            customMessage,
-        )
+        dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone, customMessage)
     }
 
     override fun shouldAnimateLaunch(isActivityIntent: Boolean): Boolean {
@@ -565,7 +599,7 @@
         val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
             statusBarWindowControllerStore.defaultDisplay.wrapAnimationControllerIfInStatusBar(
                 rootView,
-                animationController
+                animationController,
             )
         if (controllerFromStatusBar.isPresent) {
             return controllerFromStatusBar.get()
@@ -582,7 +616,7 @@
                     notifShadeWindowControllerLazy.get(),
                     commandQueue,
                     displayId,
-                    isLaunchForActivity
+                    isLaunchForActivity,
                 )
             }
         }
@@ -596,7 +630,7 @@
      */
     private fun wrapAnimationControllerForLockscreen(
         dismissShade: Boolean,
-        animationController: ActivityTransitionAnimator.Controller?
+        animationController: ActivityTransitionAnimator.Controller?,
     ): ActivityTransitionAnimator.Controller? {
         return animationController?.let {
             object : DelegateTransitionAnimatorController(it) {
@@ -613,7 +647,7 @@
                         communalSceneInteractor.snapToScene(
                             newScene = CommunalScenes.Blank,
                             loggingReason = "ActivityStarterInternalImpl",
-                            delayMillis = ActivityTransitionAnimator.TIMINGS.totalDuration
+                            delayMillis = ActivityTransitionAnimator.TIMINGS.totalDuration,
                         )
                     }
                 }
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 7bea480..2bc417e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -21,9 +21,10 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.WindowVisibleState;
 import static android.app.StatusBarManager.windowStateToString;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
 
-import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
 import static androidx.lifecycle.Lifecycle.State.RESUMED;
 
 import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
@@ -52,7 +53,6 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.hardware.devicestate.DeviceStateManager;
-import android.hardware.fingerprint.FingerprintManager;
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Binder;
@@ -65,7 +65,6 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
@@ -131,13 +130,11 @@
 import com.android.systemui.emergency.EmergencyGesture;
 import com.android.systemui.emergency.EmergencyGestureModule.EmergencyGestureIntentFactory;
 import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.MigrateClocksToBlueprint;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.navigationbar.NavigationBarController;
@@ -207,6 +204,7 @@
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -221,7 +219,6 @@
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.window.StatusBarWindowControllerStore;
@@ -250,7 +247,6 @@
 
 import javax.inject.Inject;
 import javax.inject.Named;
-import javax.inject.Provider;
 
 /**
  * A class handling initialization and coordination between some of the key central surfaces in
@@ -379,15 +375,6 @@
     private PowerButtonReveal mPowerButtonReveal;
 
     /**
-     * Whether we should delay the wakeup animation (which shows the notifications and moves the
-     * clock view). This is typically done when waking up from a 'press to unlock' gesture on a
-     * device with a side fingerprint sensor, so that if the fingerprint scan is successful, we
-     * can play the unlock animation directly rather than interrupting the wakeup animation part
-     * way through.
-     */
-    private boolean mShouldDelayWakeUpAnimation = false;
-
-    /**
      * Whether we should delay the AOD->Lockscreen animation.
      * If false, the animation will start in onStartedWakingUp().
      * If true, the animation will start in onFinishedWakingUp().
@@ -449,7 +436,6 @@
     private final MessageRouter mMessageRouter;
     private final WallpaperManager mWallpaperManager;
     private final UserTracker mUserTracker;
-    private final Provider<FingerprintManager> mFingerprintManager;
     private final ActivityStarter mActivityStarter;
 
     private final DisplayMetrics mDisplayMetrics;
@@ -701,7 +687,6 @@
             LightRevealScrim lightRevealScrim,
             AlternateBouncerInteractor alternateBouncerInteractor,
             UserTracker userTracker,
-            Provider<FingerprintManager> fingerprintManager,
             ActivityStarter activityStarter,
             BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor,
             GlanceableHubContainerController glanceableHubContainerController,
@@ -797,7 +782,6 @@
         mCameraLauncherLazy = cameraLauncherLazy;
         mAlternateBouncerInteractor = alternateBouncerInteractor;
         mUserTracker = userTracker;
-        mFingerprintManager = fingerprintManager;
         mActivityStarter = activityStarter;
         mBrightnessMirrorShowingInteractor = brightnessMirrorShowingInteractor;
         if (!SceneContainerFlag.isEnabled()) {
@@ -1522,9 +1506,9 @@
         return (v, event) -> {
             mAutoHideController.checkUserAutoHide(event);
             mRemoteInputManager.checkRemoteInputOutside(event);
-            if (!MigrateClocksToBlueprint.isEnabled() || mQsController.isCustomizing()) {
-                // For migrate clocks flag, when the user is editing QS tiles they need to be able
-                // to touch outside the customizer to close it, such as on the status or nav bar.
+            if (mQsController.isCustomizing()) {
+                // When the user is editing QS tiles they need to be able to touch outside the
+                // customizer to close it, such as on the status or nav bar.
                 mShadeController.onStatusBarTouch(event);
             }
             return getNotificationShadeWindowView().onTouchEvent(event);
@@ -2239,11 +2223,6 @@
             }
         }
         if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
-            if (!mStatusBarStateController.isKeyguardRequested()) {
-                if (!MigrateClocksToBlueprint.isEnabled()) {
-                    mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
-                }
-            }
             long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
             mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
 
@@ -2352,10 +2331,6 @@
         }
     }
 
-    public boolean shouldDelayWakeUpAnimation() {
-        return mShouldDelayWakeUpAnimation;
-    }
-
     private void updateDozingState() {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
             Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, "Dozing", 0);
@@ -2514,12 +2489,15 @@
      * should update only the status bar components.
      */
     private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) {
-        int importance = bouncerShowing
-                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
-                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
         if (!StatusBarConnectedDisplays.isEnabled() && mPhoneStatusBarViewController != null) {
+            int importance = bouncerShowing
+                    ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                    : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
             mPhoneStatusBarViewController.setImportantForAccessibility(importance);
         }
+        int importance = bouncerShowing
+                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                : IMPORTANT_FOR_ACCESSIBILITY_NO;
         mShadeSurface.setImportantForAccessibility(importance);
         mShadeSurface.setBouncerShowing(bouncerShowing);
     }
@@ -2590,55 +2568,12 @@
             DejankUtils.startDetectingBlockingIpcs(tag);
             mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
                 mDeviceInteractive = true;
-
-                boolean isFlaggedOff = MigrateClocksToBlueprint.isEnabled();
-                if (!isFlaggedOff && shouldAnimateDozeWakeup()) {
-                    // If this is false, the power button must be physically pressed in order to
-                    // trigger fingerprint authentication.
-                    final boolean touchToUnlockAnytime = Settings.Secure.getIntForUser(
-                            mContext.getContentResolver(),
-                            Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
-                            -1,
-                            mUserTracker.getUserId()) > 0;
-
-                    // Delay if we're waking up, not mid-doze animation (which means we are
-                    // cancelling a sleep), from the power button, on a device with a power button
-                    // FPS, and 'press to unlock' is required.
-                    mShouldDelayWakeUpAnimation =
-                            !mDozeServiceHost.isPulsing()
-                                    && mStatusBarStateController.getDozeAmount() == 1f
-                                    && mWakefulnessLifecycle.getLastWakeReason()
-                                    == PowerManager.WAKE_REASON_POWER_BUTTON
-                                    && mFingerprintManager.get() != null
-                                    && mFingerprintManager.get().isPowerbuttonFps()
-                                    && mKeyguardUpdateMonitor
-                                    .isUnlockWithFingerprintPossible(
-                                            mUserTracker.getUserId())
-                                    && !touchToUnlockAnytime;
-                    if (DEBUG_WAKEUP_DELAY) {
-                        Log.d(TAG, "mShouldDelayWakeUpAnimation=" + mShouldDelayWakeUpAnimation);
-                    }
-                } else {
-                    // If we're not animating anyway, we do not need to delay it.
-                    mShouldDelayWakeUpAnimation = false;
-                    if (DEBUG_WAKEUP_DELAY) {
-                        Log.d(TAG, "mShouldDelayWakeUpAnimation CLEARED");
-                    }
-                }
-
-                mShadeSurface.setWillPlayDelayedDozeAmountAnimation(
-                        mShouldDelayWakeUpAnimation);
-                mWakeUpCoordinator.setWakingUp(
-                        /* wakingUp= */ true,
-                        mShouldDelayWakeUpAnimation);
-
+                mWakeUpCoordinator.setWakingUp(true);
                 updateIsKeyguard();
                 // TODO(b/301913237): can't delay transition if config_displayBlanksAfterDoze=true,
                 // otherwise, the clock will flicker during LOCKSCREEN_TRANSITION_FROM_AOD
                 mShouldDelayLockscreenTransitionFromAod = mDozeParameters.getAlwaysOn()
-                        && !mDozeParameters.getDisplayNeedsBlanking()
-                        && mFeatureFlags.isEnabled(
-                                Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD);
+                        && !mDozeParameters.getDisplayNeedsBlanking();
                 if (!mShouldDelayLockscreenTransitionFromAod) {
                     startLockscreenTransitionFromAod();
                 }
@@ -2674,7 +2609,7 @@
                         this::startLockscreenTransitionFromAod);
             }
             mWakeUpCoordinator.setFullyAwake(true);
-            mWakeUpCoordinator.setWakingUp(false, false);
+            mWakeUpCoordinator.setWakingUp(false);
             if (mKeyguardStateController.isOccluded()
                     && !mDozeParameters.canControlUnlockedScreenOff()) {
                 // When the keyguard is occluded we don't use the KEYGUARD state which would
@@ -2727,7 +2662,6 @@
         @Override
         public void onScreenTurningOn() {
             mFalsingCollector.onScreenTurningOn();
-            mShadeSurface.onScreenTurningOn();
         }
 
         @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 57e26d7..6922de5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -340,7 +340,6 @@
     public void dozeTimeTick() {
         TraceUtils.trace("DozeServiceHost#dozeTimeTick", () -> {
             mDozeInteractor.dozeTimeTick();
-            mShadeLockscreenInteractor.dozeTimeTick();
             mAuthController.dozeTimeTick();
             if (mAmbientIndicationContainer instanceof DozeReceiver) {
                 ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 013903a..656ab0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -16,24 +16,14 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInScale;
-import static com.android.systemui.statusbar.notification.NotificationUtils.interpolate;
-
 import android.content.Context;
 import android.content.res.Resources;
-import android.util.MathUtils;
 
-import com.android.app.animation.Interpolators;
-import com.android.keyguard.BouncerPanelExpansionCalculator;
-import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.log.LogBuffer;
 import com.android.systemui.log.core.Logger;
 import com.android.systemui.log.dagger.KeyguardClockLog;
 import com.android.systemui.res.R;
 import com.android.systemui.shade.LargeScreenHeaderHelper;
-import com.android.systemui.shade.ShadeViewController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherListView;
 
 import javax.inject.Inject;
 
@@ -45,44 +35,6 @@
     private static final boolean DEBUG = false;
 
     /**
-     * Margin between the bottom of the status view and the notification shade.
-     */
-    private int mStatusViewBottomMargin;
-
-    /**
-     * Height of {@link KeyguardStatusView}.
-     */
-    private int mKeyguardStatusHeight;
-
-    /**
-     * Height of user avatar used by the multi-user switcher. This could either be the
-     * {@link KeyguardUserSwitcherListView} when it is closed and only the current user's icon is
-     * visible, or it could be height of the avatar used by the
-     * {@link com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController}.
-     */
-    private int mUserSwitchHeight;
-
-    /**
-     * Preferred Y position of user avatar used by the multi-user switcher.
-     */
-    private int mUserSwitchPreferredY;
-
-    /**
-     * Minimum top margin to avoid overlap with status bar or multi-user switcher avatar.
-     */
-    private int mMinTopMargin;
-
-    /**
-     * Minimum top inset (in pixels) to avoid overlap with any display cutouts.
-     */
-    private int mCutoutTopInset = 0;
-
-    /**
-     * Recommended distance from the status bar.
-     */
-    private int mContainerTopPadding;
-
-    /**
      * Top margin of notifications introduced by presence of split shade header / status bar
      */
     private int mSplitShadeTopNotificationsMargin;
@@ -93,35 +45,10 @@
     private int mSplitShadeTargetTopMargin;
 
     /**
-     * @see ShadeViewController#getExpandedFraction()
-     */
-    private float mPanelExpansion;
-
-    /**
-     * Max burn-in prevention x translation.
-     */
-    private int mMaxBurnInPreventionOffsetX;
-
-    /**
-     * Max burn-in prevention y translation for clock layouts.
-     */
-    private int mMaxBurnInPreventionOffsetYClock;
-
-    /**
-     * Current burn-in prevention y translation.
-     */
-    private float mCurrentBurnInOffsetY;
-
-    /**
      * Doze/AOD transition amount.
      */
     private float mDarkAmount;
 
-    /**
-     * How visible the quick settings panel is.
-     */
-    private float mQsExpansion;
-
     private float mOverStretchAmount;
 
     /**
@@ -137,25 +64,6 @@
 
     private boolean mIsSplitShade;
 
-    /**
-     * Top location of the udfps icon. This includes the worst case (highest) burn-in
-     * offset that would make the top physically highest on the screen.
-     *
-     * Set to -1 if udfps is not enrolled on the device.
-     */
-    private float mUdfpsTop;
-
-    /**
-     * Bottom y-position of the currently visible clock
-     */
-    private float mClockBottom;
-
-    /**
-     * If true, try to keep clock aligned to the top of the display. Else, assume the clock
-     * is center aligned.
-     */
-    private boolean mIsClockTopAligned;
-
     private Logger mLogger;
 
     @Inject
@@ -165,251 +73,52 @@
 
     /** Refreshes the dimension values. */
     public void loadDimens(Context context, Resources res) {
-        mStatusViewBottomMargin =
-                res.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin);
         mSplitShadeTopNotificationsMargin =
                 LargeScreenHeaderHelper.getLargeScreenHeaderHeight(context);
         mSplitShadeTargetTopMargin =
                 res.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin);
-
-        mContainerTopPadding =
-                res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin);
-        mMaxBurnInPreventionOffsetX = res.getDimensionPixelSize(
-                R.dimen.burn_in_prevention_offset_x);
-        mMaxBurnInPreventionOffsetYClock = res.getDimensionPixelSize(
-                R.dimen.burn_in_prevention_offset_y_clock);
     }
 
     /**
      * Sets up algorithm values.
      */
-    public void setup(int keyguardStatusBarHeaderHeight, float panelExpansion,
-            int keyguardStatusHeight, int userSwitchHeight, int userSwitchPreferredY,
-            float dark, float overStretchAmount, boolean bypassEnabled,
-            int unlockedStackScrollerPadding, float qsExpansion, int cutoutTopInset,
-            boolean isSplitShade, float udfpsTop, float clockBottom, boolean isClockTopAligned) {
-        mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
-                userSwitchHeight);
-        mPanelExpansion = BouncerPanelExpansionCalculator
-                .getKeyguardClockScaledExpansion(panelExpansion);
-        mKeyguardStatusHeight = keyguardStatusHeight + mStatusViewBottomMargin;
-        mUserSwitchHeight = userSwitchHeight;
-        mUserSwitchPreferredY = userSwitchPreferredY;
+    public void setup(float dark, float overStretchAmount, boolean bypassEnabled,
+            int unlockedStackScrollerPadding, boolean isSplitShade) {
         mDarkAmount = dark;
         mOverStretchAmount = overStretchAmount;
         mBypassEnabled = bypassEnabled;
         mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
-        mQsExpansion = qsExpansion;
-        mCutoutTopInset = cutoutTopInset;
         mIsSplitShade = isSplitShade;
-        mUdfpsTop = udfpsTop;
-        mClockBottom = clockBottom;
-        mIsClockTopAligned = isClockTopAligned;
     }
 
     public void run(Result result) {
-        final int y = getClockY(mPanelExpansion, mDarkAmount);
-        result.clockY = y;
-        result.userSwitchY = getUserSwitcherY(mPanelExpansion);
-        result.clockYFullyDozing = getClockY(
-                1.0f /* panelExpansion */, 1.0f /* darkAmount */);
-        result.clockAlpha = getClockAlpha(y);
-        result.stackScrollerPadding = getStackScrollerPadding(y);
+        result.stackScrollerPadding = getStackScrollerPadding();
         result.stackScrollerPaddingExpanded = getStackScrollerPaddingExpanded();
-        result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
-        result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
     }
 
     private int getStackScrollerPaddingExpanded() {
         if (mBypassEnabled) {
             return mUnlockedStackScrollerPadding;
         } else if (mIsSplitShade) {
-            return getClockY(1.0f, mDarkAmount) + mUserSwitchHeight;
+            return mSplitShadeTargetTopMargin;
         } else {
-            return getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+            return 0;
         }
     }
 
-    private int getStackScrollerPadding(int clockYPosition) {
+    private int getStackScrollerPadding() {
         if (mBypassEnabled) {
             return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
         } else if (mIsSplitShade) {
             // mCurrentBurnInOffsetY is subtracted to make notifications not follow clock adjustment
             // for burn-in. It can make pulsing notification go too high and it will get clipped
-            return clockYPosition - mSplitShadeTopNotificationsMargin + mUserSwitchHeight
-                    - (int) mCurrentBurnInOffsetY;
+            return mSplitShadeTargetTopMargin - mSplitShadeTopNotificationsMargin;
         } else {
-            return clockYPosition + mKeyguardStatusHeight;
+            return 0;
         }
     }
 
-    /**
-     * @param nsslTop NotificationStackScrollLayout top, which is below top of the srceen.
-     * @return Distance from nsslTop to top of the first view in the lockscreen shade.
-     */
-    public float getLockscreenNotifPadding(float nsslTop) {
-        if (mBypassEnabled) {
-            return mUnlockedStackScrollerPadding - nsslTop;
-        } else if (mIsSplitShade) {
-            return mSplitShadeTargetTopMargin + mUserSwitchHeight - nsslTop;
-        } else {
-            // Non-bypass portrait shade already uses values from nsslTop
-            // so we don't need to subtract it here.
-            return mMinTopMargin + mKeyguardStatusHeight;
-        }
-    }
-
-    /**
-     * give the static topMargin, used for lockscreen clocks to get the initial translationY
-     * to do counter translation
-     */
-    public int getExpandedPreferredClockY() {
-        if (mIsSplitShade) {
-            return mSplitShadeTargetTopMargin;
-        } else {
-            return mMinTopMargin;
-        }
-    }
-
-    public int getLockscreenStatusViewHeight() {
-        return mKeyguardStatusHeight;
-    }
-
-    private int getClockY(float panelExpansion, float darkAmount) {
-        float clockYRegular = getExpandedPreferredClockY();
-
-        // Dividing the height creates a smoother transition when the user swipes up to unlock
-        float clockYBouncer = -mKeyguardStatusHeight / 3.0f;
-
-        // Move clock up while collapsing the shade
-        float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
-        float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
-
-        // This will keep the clock at the top but out of the cutout area
-        float shift = 0;
-        if (clockY - mMaxBurnInPreventionOffsetYClock < mCutoutTopInset) {
-            shift = mCutoutTopInset - (clockY - mMaxBurnInPreventionOffsetYClock);
-        }
-
-        int burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock; // requested offset
-        final boolean hasUdfps = mUdfpsTop > -1;
-        if (hasUdfps && !mIsClockTopAligned) {
-            // ensure clock doesn't overlap with the udfps icon
-            if (mUdfpsTop < mClockBottom) {
-                // sometimes the clock textView extends beyond udfps, so let's just use the
-                // space above the KeyguardStatusView/clock as our burn-in offset
-                burnInPreventionOffsetY = (int) (clockY - mCutoutTopInset) / 2;
-                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
-                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
-                }
-                shift = -burnInPreventionOffsetY;
-            } else {
-                float upperSpace = clockY - mCutoutTopInset;
-                float lowerSpace = mUdfpsTop - mClockBottom;
-                // center the burn-in offset within the upper + lower space
-                burnInPreventionOffsetY = (int) (lowerSpace + upperSpace) / 2;
-                if (mMaxBurnInPreventionOffsetYClock < burnInPreventionOffsetY) {
-                    burnInPreventionOffsetY = mMaxBurnInPreventionOffsetYClock;
-                }
-                shift = (lowerSpace - upperSpace) / 2;
-            }
-        }
-
-        float fullyDarkBurnInOffset = burnInPreventionOffsetY(burnInPreventionOffsetY);
-        float clockYDark = clockY + fullyDarkBurnInOffset + shift;
-        mCurrentBurnInOffsetY = MathUtils.lerp(0, fullyDarkBurnInOffset, darkAmount);
-
-        if (DEBUG) {
-            final float finalShift = shift;
-            final float finalBurnInPreventionOffsetY = burnInPreventionOffsetY;
-            mLogger.i(msg -> {
-                final String inputs = "panelExpansion: " + panelExpansion
-                        + " darkAmount: " + darkAmount;
-                final String outputs = "clockY: " + clockY
-                        + " burnInPreventionOffsetY: " + finalBurnInPreventionOffsetY
-                        + " fullyDarkBurnInOffset: " + fullyDarkBurnInOffset
-                        + " shift: " + finalShift
-                        + " mOverStretchAmount: " + mOverStretchAmount
-                        + " mCurrentBurnInOffsetY: " + mCurrentBurnInOffsetY;
-                return inputs + " -> " + outputs;
-            }, msg -> {
-                return kotlin.Unit.INSTANCE;
-            });
-        }
-        return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
-    }
-
-    private int getUserSwitcherY(float panelExpansion) {
-        float userSwitchYRegular = mUserSwitchPreferredY;
-        float userSwitchYBouncer = -mKeyguardStatusHeight - mUserSwitchHeight;
-
-        // Move user-switch up while collapsing the shade
-        float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
-        float userSwitchY = MathUtils.lerp(userSwitchYBouncer, userSwitchYRegular, shadeExpansion);
-
-        return (int) (userSwitchY + mOverStretchAmount);
-    }
-
-    /**
-     * We might want to fade out the clock when the user is swiping up.
-     * One exception is when the bouncer will become visible, in this cause the clock
-     * should always persist.
-     *
-     * @param y Current clock Y.
-     * @return Alpha from 0 to 1.
-     */
-    private float getClockAlpha(int y) {
-        float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f, mDarkAmount)));
-        if (!mIsSplitShade) {
-            // in split shade QS are always expanded so this factor shouldn't apply
-            float qsAlphaFactor = MathUtils.saturate(mQsExpansion / 0.3f);
-            qsAlphaFactor = 1f - qsAlphaFactor;
-            alphaKeyguard *= qsAlphaFactor;
-        }
-        alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
-        return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
-    }
-
-    private float burnInPreventionOffsetY(int offset) {
-        return getBurnInOffset(offset * 2, false /* xAxis */) - offset;
-    }
-
-    private float burnInPreventionOffsetX() {
-        return getBurnInOffset(mMaxBurnInPreventionOffsetX, true /* xAxis */);
-    }
-
     public static class Result {
-
-        /**
-         * The x translation of the clock.
-         */
-        public int clockX;
-
-        /**
-         * The y translation of the clock.
-         */
-        public int clockY;
-
-        /**
-         * The y translation of the multi-user switch.
-         */
-        public int userSwitchY;
-
-        /**
-         * The y translation of the clock when we're fully dozing.
-         */
-        public int clockYFullyDozing;
-
-        /**
-         * The alpha value of the clock.
-         */
-        public float clockAlpha;
-
-        /**
-         * Amount to scale the large clock (0.0 - 1.0)
-         */
-        public float clockScale;
-
         /**
          * The top padding of the stack scroller, in pixels.
          */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
index d7cc65d..d7a29c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.Flags.mediaLockscreenLaunchAnimation
 import com.android.systemui.animation.ActivityTransitionAnimator
 import com.android.systemui.animation.DelegateTransitionAnimatorController
+import com.android.systemui.animation.TransitionAnimator
 import com.android.systemui.assist.AssistManager
 import com.android.systemui.camera.CameraIntents
 import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
@@ -98,6 +99,44 @@
     private val centralSurfaces: CentralSurfaces?
         get() = centralSurfacesOptLazy.get().getOrNull()
 
+    override fun registerTransition(
+        cookie: ActivityTransitionAnimator.TransitionCookie,
+        controllerFactory: ActivityTransitionAnimator.ControllerFactory,
+    ) {
+        check(TransitionAnimator.longLivedReturnAnimationsEnabled())
+
+        val factory =
+            object :
+                ActivityTransitionAnimator.ControllerFactory(
+                    controllerFactory.cookie,
+                    controllerFactory.component,
+                    controllerFactory.launchCujType,
+                    controllerFactory.returnCujType,
+                ) {
+                override fun createController(
+                    forLaunch: Boolean
+                ): ActivityTransitionAnimator.Controller {
+                    val baseController = controllerFactory.createController(forLaunch)
+                    val rootView = baseController.transitionContainer.rootView
+                    val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
+                        statusBarWindowControllerStore.defaultDisplay
+                            .wrapAnimationControllerIfInStatusBar(rootView, baseController)
+                    return if (controllerFromStatusBar.isPresent) {
+                        controllerFromStatusBar.get()
+                    } else {
+                        baseController
+                    }
+                }
+            }
+
+        activityTransitionAnimator.register(cookie, factory)
+    }
+
+    override fun unregisterTransition(cookie: ActivityTransitionAnimator.TransitionCookie) {
+        check(TransitionAnimator.longLivedReturnAnimationsEnabled())
+        activityTransitionAnimator.unregister(cookie)
+    }
+
     override fun startActivityDismissingKeyguard(
         intent: Intent,
         dismissShade: Boolean,
@@ -116,7 +155,7 @@
         val willLaunchResolverActivity: Boolean =
             activityIntentHelper.wouldLaunchResolverActivity(
                 intent,
-                lockScreenUserManager.currentUserId
+                lockScreenUserManager.currentUserId,
             )
 
         val animate =
@@ -147,7 +186,7 @@
             activityTransitionAnimator.startIntentWithAnimation(
                 animController,
                 animate,
-                intent.getPackage()
+                intent.getPackage(),
             ) { adapter: RemoteAnimationAdapter? ->
                 val options =
                     ActivityOptions(CentralSurfaces.getActivityOptions(displayId, adapter))
@@ -259,7 +298,7 @@
                 (skipLockscreenChecks ||
                     activityIntentHelper.wouldPendingShowOverLockscreen(
                         intent,
-                        lockScreenUserManager.currentUserId
+                        lockScreenUserManager.currentUserId,
                     ))
 
         val animate =
@@ -317,7 +356,7 @@
                                 null,
                                 null,
                                 null,
-                                options.toBundle()
+                                options.toBundle(),
                             )
                         }
                     },
@@ -409,7 +448,7 @@
             controller,
             animate,
             intent.getPackage(),
-            showOverLockscreenWhenLocked
+            showOverLockscreenWhenLocked,
         ) { adapter: RemoteAnimationAdapter? ->
             TaskStackBuilder.create(context)
                 .addNextIntent(intent)
@@ -495,12 +534,7 @@
                     return willAnimateOnKeyguard
                 }
             }
-        dismissKeyguardThenExecute(
-            onDismissAction,
-            cancelAction,
-            afterKeyguardGone,
-            customMessage,
-        )
+        dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone, customMessage)
     }
 
     /**
@@ -528,7 +562,7 @@
         val controllerFromStatusBar: Optional<ActivityTransitionAnimator.Controller> =
             statusBarWindowControllerStore.defaultDisplay.wrapAnimationControllerIfInStatusBar(
                 rootView,
-                animationController
+                animationController,
             )
         if (controllerFromStatusBar.isPresent) {
             return controllerFromStatusBar.get()
@@ -545,7 +579,7 @@
                     notifShadeWindowControllerLazy.get(),
                     commandQueue,
                     displayId,
-                    isLaunchForActivity
+                    isLaunchForActivity,
                 )
             }
         }
@@ -559,7 +593,7 @@
      */
     private fun wrapAnimationControllerForLockscreen(
         dismissShade: Boolean,
-        animationController: ActivityTransitionAnimator.Controller?
+        animationController: ActivityTransitionAnimator.Controller?,
     ): ActivityTransitionAnimator.Controller? {
         return animationController?.let {
             object : DelegateTransitionAnimatorController(it) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index f8eae36..a2b4e7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -617,7 +617,8 @@
         mUiBgExecutor.execute(() -> {
             try {
                 final int userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
-                final int iconResId = mUserManager.getUserStatusBarIconResId(userId);
+                final int iconResId = mUserManager.isProfile(userId) ?
+                        mUserManager.getUserStatusBarIconResId(userId) : Resources.ID_NULL;
                 mMainExecutor.execute(() -> {
                     final boolean showIcon;
                     if (iconResId != Resources.ID_NULL && (!mKeyguardStateController.isShowing()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index bd1360f..3749b96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -1178,7 +1178,6 @@
     public void startPreHideAnimation(Runnable finishRunnable) {
         if (primaryBouncerIsShowing()) {
             mPrimaryBouncerInteractor.startDisappearAnimation(finishRunnable);
-            mShadeLockscreenInteractor.startBouncerPreHideAnimation();
 
             // We update the state (which will show the keyguard) only if an animation will run on
             // the keyguard. If there is no animation, we wait before updating the state so that we
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 0fac644..4d1d64e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -251,11 +251,11 @@
         mPowerInteractor.wakeUpIfDozing("NOTIFICATION_CLICK", PowerManager.WAKE_REASON_GESTURE);
         if (nowExpanded) {
             if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
-                mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
-            } else if (clickedEntry.isSensitive().getValue()
-                    && isInLockedDownShade()) {
+                mShadeTransitionController.goToLockedShade(
+                        clickedEntry.getRow(), /* needsQSAnimation = */ true);
+            } else if (clickedEntry.isSensitive().getValue() && isInLockedDownShade()) {
                 mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
-                // launch the bouncer
+                // launch the bouncer if the device is locked
                 mActivityStarter.dismissKeyguardThenExecute(() -> false /* dismissAction */
                         , null /* cancelRunnable */, false /* afterKeyguardGone */);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index c53558e..76f10b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.Flags.lightRevealMigration
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.KeyguardViewMediator
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.shade.ShadeViewController
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
@@ -87,7 +86,6 @@
     private var animatorDurationScale = 1f
     private var shouldAnimateInKeyguard = false
     private var lightRevealAnimationPlaying = false
-    private var aodUiAnimationPlaying = false
 
     /**
      * The result of our decision whether to play the screen off animation in
@@ -131,7 +129,7 @@
                     override fun onAnimationStart(animation: Animator) {
                         interactionJankMonitor.begin(
                             notifShadeWindowControllerLazy.get().windowRootView,
-                            CUJ_SCREEN_OFF
+                            CUJ_SCREEN_OFF,
                         )
                     }
                 }
@@ -155,7 +153,7 @@
     override fun initialize(
         centralSurfaces: CentralSurfaces,
         shadeViewController: ShadeViewController,
-        lightRevealScrim: LightRevealScrim
+        lightRevealScrim: LightRevealScrim,
     ) {
         this.initialized = true
         this.lightRevealScrim = lightRevealScrim
@@ -165,7 +163,7 @@
         globalSettings.registerContentObserverSync(
             Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
             /* notify for descendants */ false,
-            animatorDurationScaleObserver
+            animatorDurationScaleObserver,
         )
         wakefulnessLifecycle.addObserver(this)
     }
@@ -203,7 +201,7 @@
             AnimatableProperty.Y,
             currentY,
             AnimationProperties().setDuration(duration.toLong()),
-            true /* animate */
+            true, /* animate */
         )
 
         // Cancel any existing CUJs before starting the animation
@@ -217,8 +215,6 @@
                 .setDelay(0)
                 .setDuration(duration.toLong())
                 .setAnimationEndAction {
-                    aodUiAnimationPlaying = false
-
                     // Lock the keyguard if it was waiting for the screen off animation to end.
                     keyguardViewMediatorLazy.get().maybeHandlePendingLock()
 
@@ -239,17 +235,16 @@
                     // will not be called, which is what we want since that will finish the
                     // screen off animation and show the lockscreen, which we don't want if we
                     // were cancelled.
-                    aodUiAnimationPlaying = false
                     decidedToAnimateGoingToSleep = null
                     interactionJankMonitor.cancel(CUJ_SCREEN_OFF_SHOW_AOD)
                 }
                 .setCustomInterpolator(View.ALPHA, Interpolators.FAST_OUT_SLOW_IN),
-            true /* animate */
+            true, /* animate */
         )
         val builder =
             InteractionJankMonitor.Configuration.Builder.withView(
                     InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD,
-                    checkNotNull(notifShadeWindowControllerLazy.get().windowRootView)
+                    checkNotNull(notifShadeWindowControllerLazy.get().windowRootView),
                 )
                 .setTag(statusBarStateControllerImpl.getClockId())
 
@@ -267,11 +262,6 @@
     }
 
     override fun onFinishedWakingUp() {
-        // Set this to false in onFinishedWakingUp rather than onStartedWakingUp so that other
-        // observers (such as CentralSurfaces) can ask us whether we were playing the screen off
-        // animation and reset accordingly.
-        aodUiAnimationPlaying = false
-
         // If we can't control the screen off animation, we shouldn't mess with the
         // CentralSurfaces's keyguard state unnecessarily.
         if (dozeParameters.get().canControlUnlockedScreenOff()) {
@@ -313,19 +303,12 @@
                         !powerManager.isInteractive(Display.DEFAULT_DISPLAY) &&
                             shouldAnimateInKeyguard
                     ) {
-                        if (!MigrateClocksToBlueprint.isEnabled) {
-                            // Tracking this state should no longer be relevant, as the
-                            // isInteractive
-                            // check covers it
-                            aodUiAnimationPlaying = true
-                        }
-
                         // Show AOD. That'll cause the KeyguardVisibilityHelper to call
                         // #animateInKeyguard.
                         shadeLockscreenInteractorLazy.get().showAodUi()
                     }
                 },
-                (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong()
+                (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong(),
             )
 
             return true
@@ -362,7 +345,7 @@
         if (
             Settings.Global.getString(
                 context.contentResolver,
-                Settings.Global.ANIMATOR_DURATION_SCALE
+                Settings.Global.ANIMATOR_DURATION_SCALE,
             ) == "0"
         ) {
             return false
@@ -408,7 +391,7 @@
      * AOD UI.
      */
     override fun isAnimationPlaying(): Boolean {
-        return isScreenOffLightRevealAnimationPlaying() || aodUiAnimationPlaying
+        return isScreenOffLightRevealAnimationPlaying()
     }
 
     override fun shouldAnimateInKeyguard(): Boolean = shouldAnimateInKeyguard
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
index 2f7b243..2bfbf48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/domain/interactor/OngoingCallInteractor.kt
@@ -49,15 +49,18 @@
 /**
  * Interactor for determining whether to show a chip in the status bar for ongoing phone calls.
  *
- * This class monitors call notifications and the visibility of call apps to determine the appropriate
- * chip state. It emits:
- *  * - [OngoingCallModel.NoCall] when there is no call notification
- *  * - [OngoingCallModel.InCallWithVisibleApp] when there is a call notification but the call app is visible
- *  * - [OngoingCallModel.InCall] when there is a call notification and the call app is not visible
- *  */
+ * This class monitors call notifications and the visibility of call apps to determine the
+ * appropriate chip state. It emits:
+ * * - [OngoingCallModel.NoCall] when there is no call notification
+ * * - [OngoingCallModel.InCallWithVisibleApp] when there is a call notification but the call app is
+ *   visible
+ * * - [OngoingCallModel.InCall] when there is a call notification and the call app is not visible
+ */
 @OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
-class OngoingCallInteractor @Inject constructor(
+class OngoingCallInteractor
+@Inject
+constructor(
     @Application private val scope: CoroutineScope,
     private val activityManagerRepository: ActivityManagerRepository,
     private val statusBarModeRepositoryStore: StatusBarModeRepositoryStore,
@@ -68,44 +71,37 @@
 ) : CoreStartable {
     private val logger = Logger(logBuffer, TAG)
 
-    /**
-     * Tracks whether the call chip has been swiped away.
-     */
+    /** Tracks whether the call chip has been swiped away. */
     private val _isChipSwipedAway = MutableStateFlow(false)
     val isChipSwipedAway: StateFlow<Boolean> = _isChipSwipedAway.asStateFlow()
 
-    /**
-     * The current state of ongoing calls.
-     */
+    /** The current state of ongoing calls. */
     val ongoingCallState: StateFlow<OngoingCallModel> =
         activeNotificationsInteractor.ongoingCallNotification
             .flatMapLatest { notification ->
-                createOngoingCallStateFlow(
-                    notification = notification
-                )
+                createOngoingCallStateFlow(notification = notification)
             }
             .stateIn(
                 scope = scope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = OngoingCallModel.NoCall
+                initialValue = OngoingCallModel.NoCall,
             )
 
     @VisibleForTesting
-    val isStatusBarRequiredForOngoingCall = combine(
-        ongoingCallState,
-        isChipSwipedAway
-    ) { callState, chipSwipedAway ->
-        callState is OngoingCallModel.InCall && !chipSwipedAway
-    }
+    val isStatusBarRequiredForOngoingCall =
+        combine(ongoingCallState, isChipSwipedAway) { callState, chipSwipedAway ->
+            callState is OngoingCallModel.InCall && !chipSwipedAway
+        }
 
     @VisibleForTesting
-    val isGestureListeningEnabled = combine(
-        ongoingCallState,
-        statusBarModeRepositoryStore.defaultDisplay.isInFullscreenMode,
-        isChipSwipedAway
-    ) { callState, isFullscreen, chipSwipedAway ->
-        callState is OngoingCallModel.InCall && !chipSwipedAway && isFullscreen
-    }
+    val isGestureListeningEnabled =
+        combine(
+            ongoingCallState,
+            statusBarModeRepositoryStore.defaultDisplay.isInFullscreenMode,
+            isChipSwipedAway,
+        ) { callState, isFullscreen, chipSwipedAway ->
+            callState is OngoingCallModel.InCall && !chipSwipedAway && isFullscreen
+        }
 
     private fun createOngoingCallStateFlow(
         notification: ActiveNotificationModel?
@@ -121,7 +117,7 @@
                 creationUid = notification.uid,
                 logger = logger,
                 identifyingLogTag = TAG,
-            )
+            ),
         ) { model, isVisible ->
             deriveOngoingCallState(model, isVisible)
         }
@@ -130,22 +126,19 @@
     override fun start() {
         ongoingCallState
             .filterIsInstance<OngoingCallModel.NoCall>()
-            .onEach {
-                _isChipSwipedAway.value = false
-            }.launchIn(scope)
+            .onEach { _isChipSwipedAway.value = false }
+            .launchIn(scope)
 
-        isStatusBarRequiredForOngoingCall.onEach { statusBarRequired ->
-            setStatusBarRequiredForOngoingCall(statusBarRequired)
-        }.launchIn(scope)
+        isStatusBarRequiredForOngoingCall
+            .onEach { statusBarRequired -> setStatusBarRequiredForOngoingCall(statusBarRequired) }
+            .launchIn(scope)
 
-        isGestureListeningEnabled.onEach { isEnabled ->
-            updateGestureListening(isEnabled)
-        }.launchIn(scope)
+        isGestureListeningEnabled
+            .onEach { isEnabled -> updateGestureListening(isEnabled) }
+            .launchIn(scope)
     }
 
-    /**
-     * Callback that must run when the status bar is swiped while gesture listening is active.
-     */
+    /** Callback that must run when the status bar is swiped while gesture listening is active. */
     @VisibleForTesting
     fun onStatusBarSwiped() {
         logger.d("Status bar chip swiped away")
@@ -154,13 +147,11 @@
 
     private fun deriveOngoingCallState(
         model: ActiveNotificationModel,
-        isVisible: Boolean
+        isVisible: Boolean,
     ): OngoingCallModel {
         return when {
             isVisible -> {
-                logger.d({ "Call app is visible: uid=$int1" }) {
-                    int1 = model.uid
-                }
+                logger.d({ "Call app is visible: uid=$int1" }) { int1 = model.uid }
                 OngoingCallModel.InCallWithVisibleApp
             }
 
@@ -173,7 +164,7 @@
                     startTimeMs = model.whenTime,
                     notificationIconView = model.statusBarChipIconView,
                     intent = model.contentIntent,
-                    notificationKey = model.key
+                    notificationKey = model.key,
                 )
             }
         }
@@ -186,8 +177,9 @@
         statusBarModeRepositoryStore.defaultDisplay.setOngoingProcessRequiresStatusBarVisible(
             statusBarRequired
         )
-        statusBarWindowControllerStore.defaultDisplay
-            .setOngoingProcessRequiresStatusBarVisible(statusBarRequired)
+        statusBarWindowControllerStore.defaultDisplay.setOngoingProcessRequiresStatusBarVisible(
+            statusBarRequired
+        )
     }
 
     private fun updateGestureListening(isEnabled: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
index a983ce2..9f1395a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepository.kt
@@ -21,7 +21,6 @@
 import android.provider.Settings.Global
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
@@ -65,7 +64,7 @@
     @Background private val backgroundContext: CoroutineContext,
     private val globalSettings: GlobalSettings,
     @AirplaneTableLog logger: TableLogBuffer,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
 ) : AirplaneModeRepository {
     // TODO(b/254848912): Replace this with a generic SettingObserver coroutine once we have it.
     override val isAirplaneMode: StateFlow<Boolean> =
@@ -86,7 +85,7 @@
                 logger,
                 columnPrefix = "",
                 columnName = "isAirplaneMode",
-                initialValue = false
+                initialValue = false,
             )
             .stateIn(
                 scope,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
index 5d5d562..bd18f4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
@@ -48,7 +48,7 @@
 constructor(
     interactor: AirplaneModeInteractor,
     @AirplaneTableLog logger: TableLogBuffer,
-    @Application private val scope: CoroutineScope,
+    @Background scope: CoroutineScope,
 ) : AirplaneModeViewModel {
     override val isAirplaneModeIconVisible: StateFlow<Boolean> =
         combine(interactor.isAirplaneMode, interactor.isForceHidden) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index bfdc8bd..96666d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -32,6 +32,8 @@
 import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry
 import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistryImpl
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigCoreStartable
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepositoryImpl
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileRepositorySwitcher
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
@@ -48,6 +50,8 @@
 import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
 import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel
 import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
+import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstantsImpl
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
 import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
@@ -106,6 +110,9 @@
         impl: DeviceBasedSatelliteViewModelImpl
     ): DeviceBasedSatelliteViewModel
 
+    @Binds
+    abstract fun connectivityConstants(impl: ConnectivityConstantsImpl): ConnectivityConstants
+
     @Binds abstract fun wifiRepository(impl: WifiRepositorySwitcher): WifiRepository
 
     @Binds abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
@@ -120,6 +127,9 @@
     @Binds abstract fun mobileMappingsProxy(impl: MobileMappingsProxyImpl): MobileMappingsProxy
 
     @Binds
+    abstract fun carrierConfigRepository(impl: CarrierConfigRepositoryImpl): CarrierConfigRepository
+
+    @Binds
     abstract fun subscriptionManagerProxy(
         impl: SubscriptionManagerProxyImpl
     ): SubscriptionManagerProxy
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
index 0871c86..5f33a754 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/SystemUiCarrierConfig.kt
@@ -48,11 +48,7 @@
  * 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly
  *    updated when a new carrier config comes down
  */
-class SystemUiCarrierConfig
-internal constructor(
-    val subId: Int,
-    defaultConfig: PersistableBundle,
-) {
+class SystemUiCarrierConfig constructor(val subId: Int, defaultConfig: PersistableBundle) {
     @VisibleForTesting
     var isUsingDefault = true
         private set
@@ -67,17 +63,11 @@
     /** Flow tracking the [KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL] config */
     val showOperatorNameInStatusBar: StateFlow<Boolean> = showOperatorName.config
 
-    private val showNetworkSlice =
-        BooleanCarrierConfig(KEY_SHOW_5G_SLICE_ICON_BOOL, defaultConfig)
+    private val showNetworkSlice = BooleanCarrierConfig(KEY_SHOW_5G_SLICE_ICON_BOOL, defaultConfig)
     /** Flow tracking the [KEY_SHOW_5G_SLICE_ICON_BOOL] config */
     val allowNetworkSliceIndicator: StateFlow<Boolean> = showNetworkSlice.config
 
-    private val trackedConfigs =
-        listOf(
-            inflateSignalStrength,
-            showOperatorName,
-            showNetworkSlice,
-        )
+    private val trackedConfigs = listOf(inflateSignalStrength, showOperatorName, showNetworkSlice)
 
     /** Ingest a new carrier config, and switch all of the tracked keys over to the new values */
     fun processNewCarrierConfig(config: PersistableBundle) {
@@ -98,10 +88,7 @@
 }
 
 /** Extracts [key] from the carrier config, and stores it in a flow */
-private class BooleanCarrierConfig(
-    val key: String,
-    defaultConfig: PersistableBundle,
-) {
+private class BooleanCarrierConfig(val key: String, defaultConfig: PersistableBundle) {
     private val _configValue = MutableStateFlow(defaultConfig.getBoolean(key))
     val config = _configValue.asStateFlow()
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt
index 428d16a..6bb97c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigCoreStartable.kt
@@ -16,11 +16,11 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /**
  * Core startable which configures the [CarrierConfigRepository] to listen for updates for the
@@ -30,7 +30,7 @@
 @Inject
 constructor(
     private val carrierConfigRepository: CarrierConfigRepository,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
 ) : CoreStartable {
 
     override fun start() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
index 016ba5f..30c529a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt
@@ -16,31 +16,8 @@
 
 package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
-import android.content.IntentFilter
-import android.os.PersistableBundle
 import android.telephony.CarrierConfigManager
-import android.telephony.SubscriptionManager
-import android.util.SparseArray
-import androidx.annotation.VisibleForTesting
-import androidx.core.util.getOrElse
-import androidx.core.util.isEmpty
-import androidx.core.util.keyIterator
-import com.android.systemui.Dumpable
-import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
-import java.io.PrintWriter
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.mapNotNull
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.flow.shareIn
 
 /**
  * Meant to be the source of truth regarding CarrierConfigs. These are configuration objects defined
@@ -50,87 +27,13 @@
  *
  * See [SystemUiCarrierConfig] for details on how to add carrier config keys to be tracked
  */
-@SysUISingleton
-class CarrierConfigRepository
-@Inject
-constructor(
-    broadcastDispatcher: BroadcastDispatcher,
-    private val carrierConfigManager: CarrierConfigManager?,
-    dumpManager: DumpManager,
-    logger: MobileInputLogger,
-    @Application scope: CoroutineScope,
-) : Dumpable {
-    private var isListening = false
-    private val defaultConfig: PersistableBundle by lazy { CarrierConfigManager.getDefaultConfig() }
-    // Used for logging the default config in the dumpsys
-    private val defaultConfigForLogs: SystemUiCarrierConfig by lazy {
-        SystemUiCarrierConfig(-1, defaultConfig)
-    }
-
-    private val configs = SparseArray<SystemUiCarrierConfig>()
-
-    init {
-        dumpManager.registerNormalDumpable(this)
-    }
-
-    @VisibleForTesting
-    val carrierConfigStream: SharedFlow<Pair<Int, PersistableBundle>> =
-        broadcastDispatcher
-            .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
-                intent,
-                _ ->
-                intent.getIntExtra(
-                    CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
-                    SubscriptionManager.INVALID_SUBSCRIPTION_ID
-                )
-            }
-            .onEach { logger.logCarrierConfigChanged(it) }
-            .filter { SubscriptionManager.isValidSubscriptionId(it) }
-            .mapNotNull { subId ->
-                val config = carrierConfigManager?.getConfigForSubId(subId)
-                config?.let { subId to it }
-            }
-            .shareIn(scope, SharingStarted.WhileSubscribed())
-
+interface CarrierConfigRepository {
     /**
      * Start this repository observing broadcasts for **all** carrier configuration updates. Must be
      * called in order to keep SystemUI in sync with [CarrierConfigManager].
      */
-    suspend fun startObservingCarrierConfigUpdates() {
-        isListening = true
-        carrierConfigStream.collect { updateCarrierConfig(it.first, it.second) }
-    }
-
-    /** Update or create the [SystemUiCarrierConfig] for subId with the override */
-    private fun updateCarrierConfig(subId: Int, config: PersistableBundle) {
-        val configToUpdate = getOrCreateConfigForSubId(subId)
-        configToUpdate.processNewCarrierConfig(config)
-    }
+    suspend fun startObservingCarrierConfigUpdates()
 
     /** Gets a cached [SystemUiCarrierConfig], or creates a new one which will track the defaults */
-    fun getOrCreateConfigForSubId(subId: Int): SystemUiCarrierConfig {
-        return configs.getOrElse(subId) {
-            val config = SystemUiCarrierConfig(subId, defaultConfig)
-            val carrierConfig = carrierConfigManager?.getConfigForSubId(subId)
-            if (carrierConfig != null) config.processNewCarrierConfig(carrierConfig)
-            configs.put(subId, config)
-            config
-        }
-    }
-
-    override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.println("isListening: $isListening")
-        if (configs.isEmpty()) {
-            pw.println("no carrier configs loaded")
-        } else {
-            pw.println("Carrier configs by subId")
-            configs.keyIterator().forEach {
-                pw.println("  subId=$it")
-                pw.println("    config=${configs.get(it).toStringConsideringDefaults()}")
-            }
-            // Finally, print the default config
-            pw.println("Default config:")
-            pw.println("  $defaultConfigForLogs")
-        }
-    }
+    fun getOrCreateConfigForSubId(subId: Int): SystemUiCarrierConfig
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImpl.kt
new file mode 100644
index 0000000..9a97f19
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImpl.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository
+
+import android.content.IntentFilter
+import android.os.PersistableBundle
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.util.SparseArray
+import androidx.annotation.VisibleForTesting
+import androidx.core.util.getOrElse
+import androidx.core.util.isEmpty
+import androidx.core.util.keyIterator
+import com.android.systemui.Dumpable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import java.io.PrintWriter
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.onEach
+
+@SysUISingleton
+class CarrierConfigRepositoryImpl
+@Inject
+constructor(
+    broadcastDispatcher: BroadcastDispatcher,
+    private val carrierConfigManager: CarrierConfigManager?,
+    dumpManager: DumpManager,
+    logger: MobileInputLogger,
+) : CarrierConfigRepository, Dumpable {
+    private var isListening = false
+    private val defaultConfig: PersistableBundle by lazy { CarrierConfigManager.getDefaultConfig() }
+    // Used for logging the default config in the dumpsys
+    private val defaultConfigForLogs: SystemUiCarrierConfig by lazy {
+        SystemUiCarrierConfig(-1, defaultConfig)
+    }
+
+    private val configs = SparseArray<SystemUiCarrierConfig>()
+
+    init {
+        dumpManager.registerNormalDumpable(this)
+    }
+
+    @VisibleForTesting
+    val carrierConfigStream: Flow<Pair<Int, PersistableBundle>> =
+        broadcastDispatcher
+            .broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+                intent,
+                _ ->
+                intent.getIntExtra(
+                    CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
+                    SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+                )
+            }
+            .onEach { logger.logCarrierConfigChanged(it) }
+            .filter { SubscriptionManager.isValidSubscriptionId(it) }
+            .mapNotNull { subId ->
+                val config = carrierConfigManager?.getConfigForSubId(subId)
+                config?.let { subId to it }
+            }
+
+    override suspend fun startObservingCarrierConfigUpdates() {
+        isListening = true
+        carrierConfigStream.collect { updateCarrierConfig(it.first, it.second) }
+    }
+
+    /** Update or create the [SystemUiCarrierConfig] for subId with the override */
+    private fun updateCarrierConfig(subId: Int, config: PersistableBundle) {
+        val configToUpdate = getOrCreateConfigForSubId(subId)
+        configToUpdate.processNewCarrierConfig(config)
+    }
+
+    override fun getOrCreateConfigForSubId(subId: Int): SystemUiCarrierConfig {
+        return configs.getOrElse(subId) {
+            val config = SystemUiCarrierConfig(subId, defaultConfig)
+            val carrierConfig = carrierConfigManager?.getConfigForSubId(subId)
+            if (carrierConfig != null) config.processNewCarrierConfig(carrierConfig)
+            configs.put(subId, config)
+            config
+        }
+    }
+
+    override fun dump(pw: PrintWriter, args: Array<out String>) {
+        pw.println("isListening: $isListening")
+        if (configs.isEmpty()) {
+            pw.println("no carrier configs loaded")
+        } else {
+            pw.println("Carrier configs by subId")
+            configs.keyIterator().forEach {
+                pw.println("  subId=$it")
+                pw.println("    config=${configs.get(it).toStringConsideringDefaults()}")
+            }
+            // Finally, print the default config
+            pw.println("Default config:")
+            pw.println("  $defaultConfigForLogs")
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
index b247da4..fc76691 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcher.kt
@@ -20,14 +20,14 @@
 import androidx.annotation.VisibleForTesting
 import com.android.settingslib.SignalIcon
 import com.android.settingslib.mobile.MobileMappings
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -67,7 +67,7 @@
 class MobileRepositorySwitcher
 @Inject
 constructor(
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
     val realRepository: MobileConnectionsRepositoryImpl,
     val demoMobileConnectionsRepository: DemoMobileConnectionsRepository,
     demoModeController: DemoModeController,
@@ -121,7 +121,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                realRepository.activeMobileDataSubscriptionId.value
+                realRepository.activeMobileDataSubscriptionId.value,
             )
 
     override val activeMobileDataRepository: StateFlow<MobileConnectionRepository?> =
@@ -130,7 +130,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                realRepository.activeMobileDataRepository.value
+                realRepository.activeMobileDataRepository.value,
             )
 
     override val activeSubChangedInGroupEvent: Flow<Unit> =
@@ -142,7 +142,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                realRepository.defaultDataSubRatConfig.value
+                realRepository.defaultDataSubRatConfig.value,
             )
 
     override val defaultMobileIconMapping: Flow<Map<String, SignalIcon.MobileIconGroup>> =
@@ -157,7 +157,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                realRepository.isDeviceEmergencyCallCapable.value
+                realRepository.isDeviceEmergencyCallCapable.value,
             )
 
     override val isAnySimSecure: Flow<Boolean> = activeRepo.flatMapLatest { it.isAnySimSecure }
@@ -189,7 +189,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                realRepository.defaultConnectionIsValidated.value
+                realRepository.defaultConnectionIsValidated.value,
             )
 
     override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
index bb9310f..936954f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt
@@ -20,10 +20,11 @@
 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
 import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
 import android.util.Log
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.settingslib.SignalIcon
 import com.android.settingslib.mobile.MobileMappings
 import com.android.settingslib.mobile.TelephonyIcons
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
 import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -51,7 +52,6 @@
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /** This repository vends out data based on demo mode commands */
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -60,7 +60,7 @@
 constructor(
     private val mobileDataSource: DemoModeMobileConnectionDataSource,
     private val wifiDataSource: DemoModeWifiDataSource,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     context: Context,
     private val logFactory: TableLogBufferFactory,
 ) : MobileConnectionsRepository {
@@ -115,7 +115,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
+                subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID,
             )
 
     override val activeMobileDataRepository: StateFlow<MobileConnectionRepository?> =
@@ -124,7 +124,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                getRepoForSubId(activeMobileDataSubscriptionId.value)
+                getRepoForSubId(activeMobileDataSubscriptionId.value),
             )
 
     // TODO(b/261029387): consider adding a demo command for this
@@ -160,7 +160,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                defaultMobileIconMapping.value.reverse()
+                defaultMobileIconMapping.value.reverse(),
             )
 
     private fun <K, V> Map<K, V>.reverse() = entries.associateBy({ it.value }) { it.key }
@@ -190,17 +190,9 @@
 
     private fun createDemoMobileConnectionRepo(subId: Int): CacheContainer {
         val tableLogBuffer =
-            logFactory.getOrCreate(
-                "DemoMobileConnectionLog[$subId]",
-                MOBILE_CONNECTION_BUFFER_SIZE,
-            )
+            logFactory.getOrCreate("DemoMobileConnectionLog[$subId]", MOBILE_CONNECTION_BUFFER_SIZE)
 
-        val repo =
-            DemoMobileConnectionRepository(
-                subId,
-                tableLogBuffer,
-                scope,
-            )
+        val repo = DemoMobileConnectionRepository(subId, tableLogBuffer, scope)
         return CacheContainer(repo, lastMobileState = null)
     }
 
@@ -297,7 +289,7 @@
                             TAG,
                             "processDisabledMobileState: Unable to infer subscription to " +
                                 "disable. Specify subId using '-e slot <subId>'" +
-                                "Known subIds: [${subIdsString()}]"
+                                "Known subIds: [${subIdsString()}]",
                         )
                         return
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt
index dbfc576..c8edb71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt
@@ -25,7 +25,7 @@
 import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.demomode.DemoMode.COMMAND_NETWORK
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
@@ -44,10 +44,7 @@
 @SysUISingleton
 class DemoModeMobileConnectionDataSource
 @Inject
-constructor(
-    demoModeController: DemoModeController,
-    @Application scope: CoroutineScope,
-) {
+constructor(demoModeController: DemoModeController, @Background scope: CoroutineScope) {
     private val demoCommandStream = demoModeController.demoFlowForCommand(COMMAND_NETWORK)
 
     // If the args contains "mobile", then all of the args are relevant. It's just the way demo mode
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
index 75f613d..db08f25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/CarrierMergedConnectionRepository.kt
@@ -21,7 +21,6 @@
 import android.telephony.TelephonyManager
 import android.util.Log
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
@@ -59,7 +58,7 @@
     override val tableLogBuffer: TableLogBuffer,
     private val telephonyManager: TelephonyManager,
     private val bgContext: CoroutineContext,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     val wifiRepository: WifiRepository,
 ) : MobileConnectionRepository {
     init {
@@ -205,7 +204,7 @@
     constructor(
         private val telephonyManager: TelephonyManager,
         @Background private val bgContext: CoroutineContext,
-        @Application private val scope: CoroutineScope,
+        @Background private val scope: CoroutineScope,
         private val wifiRepository: WifiRepository,
     ) {
         fun build(subId: Int, mobileLogger: TableLogBuffer): MobileConnectionRepository {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
index fae9be0..98aa7fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepository.kt
@@ -18,7 +18,7 @@
 
 import android.util.IndentingPrintWriter
 import androidx.annotation.VisibleForTesting
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.TableLogBufferFactory
 import com.android.systemui.log.table.logDiffsForTable
@@ -54,7 +54,7 @@
     subscriptionModel: Flow<SubscriptionModel?>,
     private val defaultNetworkName: NetworkNameModel,
     private val networkNameSeparator: String,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
     private val mobileRepoFactory: MobileConnectionRepositoryImpl.Factory,
     private val carrierMergedRepoFactory: CarrierMergedConnectionRepository.Factory,
 ) : MobileConnectionRepository {
@@ -403,7 +403,7 @@
     class Factory
     @Inject
     constructor(
-        @Application private val scope: CoroutineScope,
+        @Background private val scope: CoroutineScope,
         private val logFactory: TableLogBufferFactory,
         private val mobileRepoFactory: MobileConnectionRepositoryImpl.Factory,
         private val carrierMergedRepoFactory: CarrierMergedConnectionRepository.Factory,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index 8a1e7f9..99b4aa4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -44,8 +44,6 @@
 import android.telephony.satellite.NtnSignalStrength
 import com.android.settingslib.Utils
 import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO
@@ -66,6 +64,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -489,7 +488,7 @@
         private val mobileMappingsProxy: MobileMappingsProxy,
         private val flags: FeatureFlagsClassic,
         @Background private val bgDispatcher: CoroutineDispatcher,
-        @Application private val scope: CoroutineScope,
+        @Background private val scope: CoroutineScope,
     ) {
         fun build(
             subId: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
index b756a05..589db16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryImpl.kt
@@ -37,7 +37,6 @@
 import com.android.systemui.Dumpable
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
@@ -96,7 +95,7 @@
     broadcastDispatcher: BroadcastDispatcher,
     private val context: Context,
     @Background private val bgDispatcher: CoroutineDispatcher,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     @Main private val mainDispatcher: CoroutineDispatcher,
     airplaneModeRepository: AirplaneModeRepository,
     // Some "wifi networks" should be rendered as a mobile connection, which is why the wifi
@@ -179,7 +178,7 @@
                 val subId =
                     intent.getIntExtra(
                         SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
-                        INVALID_SUBSCRIPTION_ID
+                        INVALID_SUBSCRIPTION_ID,
                     )
 
                 // Only emit if the subId is not associated with an active subscription
@@ -268,7 +267,7 @@
     override val defaultDataSubId: StateFlow<Int> =
         broadcastDispatcher
             .broadcastFlow(
-                IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED),
+                IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
             ) { intent, _ ->
                 intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
             }
@@ -296,7 +295,7 @@
             .stateIn(
                 scope,
                 SharingStarted.WhileSubscribed(),
-                initialValue = Config.readConfig(context)
+                initialValue = Config.readConfig(context),
             )
 
     override val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>> =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractor.kt
new file mode 100644
index 0000000..8b7f345
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractor.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Business logic for [CarrierConfigRepository] */
+@SysUISingleton
+class CarrierConfigInteractor
+@Inject
+constructor(
+    repo: CarrierConfigRepository,
+    iconsInteractor: MobileIconsInteractor,
+    @Application scope: CoroutineScope,
+) {
+    val defaultDataSubscriptionCarrierConfig: StateFlow<SystemUiCarrierConfig?> =
+        iconsInteractor.defaultDataSubId
+            .map { repo.getOrCreateConfigForSubId(it) }
+            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
index 1bf14af..2a9a199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt
@@ -22,7 +22,7 @@
 import com.android.settingslib.graph.SignalDrawable
 import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
 import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
@@ -137,7 +137,7 @@
 @Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
 @OptIn(ExperimentalCoroutinesApi::class)
 class MobileIconInteractorImpl(
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
     defaultSubscriptionHasDataEnabled: StateFlow<Boolean>,
     override val alwaysShowDataRatIcon: StateFlow<Boolean>,
     alwaysUseCdmaLevel: StateFlow<Boolean>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
index 28fff4e..78731fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractor.kt
@@ -23,7 +23,7 @@
 import com.android.settingslib.SignalIcon.MobileIconGroup
 import com.android.settingslib.mobile.TelephonyIcons
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags.FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS
 import com.android.systemui.log.table.TableLogBuffer
@@ -71,6 +71,9 @@
     /** List of subscriptions, potentially filtered for CBRS */
     val filteredSubscriptions: Flow<List<SubscriptionModel>>
 
+    /** Subscription ID of the current default data subscription */
+    val defaultDataSubId: Flow<Int>
+
     /**
      * The current list of [MobileIconInteractor]s associated with the current list of
      * [filteredSubscriptions]
@@ -82,7 +85,7 @@
 
     /**
      * Flow providing a reference to the Interactor for the active data subId. This represents the
-     * [MobileConnectionInteractor] responsible for the active data connection, if any.
+     * [MobileIconInteractor] responsible for the active data connection, if any.
      */
     val activeDataIconInteractor: StateFlow<MobileIconInteractor?>
 
@@ -135,7 +138,7 @@
     @MobileSummaryLog private val tableLogger: TableLogBuffer,
     connectivityRepository: ConnectivityRepository,
     userSetupRepo: UserSetupRepository,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     private val context: Context,
     private val featureFlagsClassic: FeatureFlagsClassic,
 ) : MobileIconsInteractor {
@@ -280,6 +283,8 @@
         }
     }
 
+    override val defaultDataSubId = mobileConnectionsRepo.defaultDataSubId
+
     override val icons =
         filteredSubscriptions
             .mapLatest { subs ->
@@ -321,7 +326,7 @@
         mobileConnectionsRepo.defaultMobileIconMapping.stateIn(
             scope,
             SharingStarted.WhileSubscribed(),
-            initialValue = mapOf()
+            initialValue = mapOf(),
         )
 
     override val alwaysShowDataRatIcon: StateFlow<Boolean> =
@@ -350,7 +355,7 @@
         mobileConnectionsRepo.defaultMobileIconGroup.stateIn(
             scope,
             SharingStarted.WhileSubscribed(),
-            initialValue = TelephonyIcons.G
+            initialValue = TelephonyIcons.G,
         )
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
index 2efbfbb..2cd0117 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconsViewModel.kt
@@ -17,9 +17,10 @@
 package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
 
 import androidx.annotation.VisibleForTesting
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.coroutines.newTracingContext
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
@@ -41,7 +42,6 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
 
 /**
  * View model for describing the system's current mobile cellular connections. The result is a list
@@ -59,7 +59,7 @@
     private val airplaneModeInteractor: AirplaneModeInteractor,
     private val constants: ConnectivityConstants,
     private val flags: FeatureFlagsClassic,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
 ) {
     @VisibleForTesting
     val reuseCache = mutableMapOf<Int, Pair<MobileIconViewModel, CoroutineScope>>()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
index de42b92..70abb02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/DeviceBasedSatelliteRepositorySwitcher.kt
@@ -19,7 +19,7 @@
 import android.os.Bundle
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.statusbar.pipeline.satellite.data.demo.DemoDeviceBasedSatelliteRepository
@@ -59,7 +59,7 @@
     private val realImpl: RealDeviceBasedSatelliteRepository,
     private val demoImpl: DemoDeviceBasedSatelliteRepository,
     private val demoModeController: DemoModeController,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
 ) : DeviceBasedSatelliteRepository {
     private val isDemoMode =
         conflatedCallbackFlow {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
index f11ebc0..7aab47a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt
@@ -26,12 +26,10 @@
 import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS
 import android.telephony.satellite.SatelliteModemStateCallback
 import android.telephony.satellite.SatelliteProvisionStateCallback
-import android.telephony.satellite.SatelliteSupportedStateCallback
 import androidx.annotation.VisibleForTesting
 import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.log.LogBuffer
@@ -51,6 +49,7 @@
 import com.android.systemui.util.kotlin.pairwise
 import com.android.systemui.util.time.SystemClock
 import java.util.Optional
+import java.util.function.Consumer
 import javax.inject.Inject
 import kotlin.coroutines.resume
 import kotlinx.coroutines.CoroutineDispatcher
@@ -145,7 +144,7 @@
     satelliteManagerOpt: Optional<SatelliteManager>,
     telephonyManager: TelephonyManager,
     @Background private val bgDispatcher: CoroutineDispatcher,
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     @DeviceBasedSatelliteInputLog private val logBuffer: LogBuffer,
     @VerboseDeviceBasedSatelliteInputLog private val verboseLogBuffer: LogBuffer,
     private val systemClock: SystemClock,
@@ -322,13 +321,14 @@
             flowOf(false)
         } else {
             conflatedCallbackFlow {
-                val callback = SatelliteSupportedStateCallback { supported ->
-                    logBuffer.i {
-                        "onSatelliteSupportedStateChanged: " +
-                            "${if (supported) "supported" else "not supported"}"
+                val callback =
+                    Consumer<Boolean> { supported ->
+                        logBuffer.i {
+                            "onSatelliteSupportedStateChanged: " +
+                                "${if (supported) "supported" else "not supported"}"
+                        }
+                        trySend(supported)
                     }
-                    trySend(supported)
-                }
 
                 var registered = false
                 try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
index 12f578c..86f9c94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/domain/interactor/DeviceBasedSatelliteInteractor.kt
@@ -18,7 +18,7 @@
 
 import com.android.internal.telephony.flags.Flags
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.log.table.TableLogBuffer
@@ -49,7 +49,7 @@
     val repo: DeviceBasedSatelliteRepository,
     iconsInteractor: MobileIconsInteractor,
     wifiInteractor: WifiInteractor,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
     @DeviceBasedSatelliteInputLog private val logBuffer: LogBuffer,
     @DeviceBasedSatelliteTableLog private val tableLog: TableLogBuffer,
 ) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
index 9ea167f..09314ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstants.kt
@@ -19,9 +19,9 @@
 import android.content.Context
 import android.telephony.TelephonyManager
 import com.android.systemui.Dumpable
-import com.android.systemui.res.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.res.R
 import java.io.PrintWriter
 import javax.inject.Inject
 
@@ -30,23 +30,26 @@
  *
  * Stored in a class for logging purposes.
  */
+interface ConnectivityConstants {
+    /** True if this device has the capability for data connections and false otherwise. */
+    val hasDataCapabilities: Boolean
+
+    /** True if we should show the activityIn/activityOut icons and false otherwise */
+    val shouldShowActivityConfig: Boolean
+}
+
 @SysUISingleton
-class ConnectivityConstants
+class ConnectivityConstantsImpl
 @Inject
-constructor(
-    context: Context,
-    dumpManager: DumpManager,
-    telephonyManager: TelephonyManager,
-) : Dumpable {
+constructor(context: Context, dumpManager: DumpManager, telephonyManager: TelephonyManager) :
+    ConnectivityConstants, Dumpable {
     init {
         dumpManager.registerNormalDumpable("ConnectivityConstants", this)
     }
 
-    /** True if this device has the capability for data connections and false otherwise. */
-    val hasDataCapabilities = telephonyManager.isDataCapable
+    override val hasDataCapabilities = telephonyManager.isDataCapable
 
-    /** True if we should show the activityIn/activityOut icons and false otherwise */
-    val shouldShowActivityConfig = context.resources.getBoolean(R.bool.config_showActivity)
+    override val shouldShowActivityConfig = context.resources.getBoolean(R.bool.config_showActivity)
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
         pw.apply {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt
deleted file mode 100644
index a0cb829..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.pipeline.shared.domain.interactor
-
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.disableflags.domain.interactor.DisableFlagsInteractor
-import com.android.systemui.statusbar.pipeline.shared.domain.model.StatusBarDisableFlagsVisibilityModel
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
-
-/**
- * Interactor for the home screen status bar (aka
- * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]).
- */
-@SysUISingleton
-class CollapsedStatusBarInteractor
-@Inject
-constructor(disableFlagsInteractor: DisableFlagsInteractor) {
-    /**
-     * The visibilities of various status bar child views, based only on the information we received
-     * from disable flags.
-     */
-    val visibilityViaDisableFlags: Flow<StatusBarDisableFlagsVisibilityModel> =
-        disableFlagsInteractor.disableFlags.map {
-            StatusBarDisableFlagsVisibilityModel(
-                isClockAllowed = it.isClockEnabled,
-                areNotificationIconsAllowed = it.areNotificationIconsEnabled,
-                isSystemInfoAllowed = it.isSystemInfoEnabled,
-                animate = it.animate,
-            )
-        }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractor.kt
new file mode 100644
index 0000000..becf6e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractor.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import android.content.res.Resources
+import android.provider.Settings
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/** A place to define the blocklist/allowlist for home status bar icons */
+@SysUISingleton
+class HomeStatusBarIconBlockListInteractor
+@Inject
+constructor(@Main res: Resources, secureSettingsRepository: SecureSettingsRepository) {
+    private val defaultBlockedIcons =
+        res.getStringArray(R.array.config_collapsed_statusbar_icon_blocklist)
+
+    private val vibrateIconSlot = res.getString(com.android.internal.R.string.status_bar_volume)
+
+    /** Tracks the user setting [Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON] */
+    private val shouldShowVibrateIcon: Flow<Boolean> =
+        secureSettingsRepository.boolSetting(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, false)
+
+    val iconBlockList: Flow<List<String>> =
+        shouldShowVibrateIcon.map {
+            val defaultSet = defaultBlockedIcons.toMutableSet()
+            // It's possible that the vibrate icon was in the default blocklist, so we manually
+            // merge the setting and list
+            if (it) {
+                defaultSet.remove(vibrateIconSlot)
+            } else {
+                defaultSet.add(vibrateIconSlot)
+            }
+
+            defaultSet.toList()
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt
new file mode 100644
index 0000000..b94ef03
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractor.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.disableflags.domain.interactor.DisableFlagsInteractor
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.CarrierConfigInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.model.StatusBarDisableFlagsVisibilityModel
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+
+/**
+ * Interactor for the home screen status bar (aka
+ * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]).
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class HomeStatusBarInteractor
+@Inject
+constructor(
+    airplaneModeInteractor: AirplaneModeInteractor,
+    carrierConfigInteractor: CarrierConfigInteractor,
+    disableFlagsInteractor: DisableFlagsInteractor,
+) {
+    /**
+     * The visibilities of various status bar child views, based only on the information we received
+     * from disable flags.
+     */
+    val visibilityViaDisableFlags: Flow<StatusBarDisableFlagsVisibilityModel> =
+        disableFlagsInteractor.disableFlags.map {
+            StatusBarDisableFlagsVisibilityModel(
+                isClockAllowed = it.isClockEnabled,
+                areNotificationIconsAllowed = it.areNotificationIconsEnabled,
+                isSystemInfoAllowed = it.isSystemInfoEnabled,
+                animate = it.animate,
+            )
+        }
+
+    private val defaultDataSubConfigShowOperatorView =
+        carrierConfigInteractor.defaultDataSubscriptionCarrierConfig.flatMapLatest {
+            it?.showOperatorNameInStatusBar ?: flowOf(false)
+        }
+
+    /**
+     * True if the carrier config for the default data subscription has
+     * [SystemUiCarrierConfig.showOperatorNameInStatusBar] set and the device is not in airplane
+     * mode
+     */
+    val shouldShowOperatorName: Flow<Boolean> =
+        combine(defaultDataSubConfigShowOperatorView, airplaneModeInteractor.isAirplaneMode) {
+            showOperatorName,
+            isAirplaneMode ->
+            showOperatorName && !isAirplaneMode
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarIconBlockListBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarIconBlockListBinder.kt
new file mode 100644
index 0000000..e247f0d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarIconBlockListBinder.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.ui.binder
+
+import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.statusbar.phone.ui.IconManager
+import kotlinx.coroutines.flow.Flow
+
+object HomeStatusBarIconBlockListBinder {
+    fun bind(view: View, iconManager: IconManager, iconList: Flow<List<String>>) {
+        view.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                iconList.collect { newBlockList -> iconManager.setBlockList(newBlockList) }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
index d9b2bd1d..7e06c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/HomeStatusBarViewBinder.kt
@@ -19,6 +19,7 @@
 import android.animation.Animator
 import android.animation.AnimatorListenerAdapter
 import android.view.View
+import androidx.core.view.isVisible
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
@@ -204,6 +205,18 @@
                 }
 
                 if (StatusBarRootModernization.isEnabled) {
+                    val operatorNameView = view.requireViewById<View>(R.id.operator_name_frame)
+                    StatusBarOperatorNameViewBinder.bind(
+                        operatorNameView,
+                        viewModel.operatorNameViewModel,
+                        viewModel::areaTint,
+                    )
+                    launch {
+                        viewModel.shouldShowOperatorNameView.collect {
+                            operatorNameView.isVisible = it
+                        }
+                    }
+
                     val clockView = view.requireViewById<View>(R.id.clock)
                     launch { viewModel.isClockVisible.collect { clockView.adjustVisibility(it) } }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/StatusBarOperatorNameViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/StatusBarOperatorNameViewBinder.kt
new file mode 100644
index 0000000..b7744d3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/StatusBarOperatorNameViewBinder.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.ui.binder
+
+import android.view.View
+import android.widget.TextView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.StatusBarOperatorNameViewModel
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.StatusBarTintColor
+import com.android.systemui.util.view.viewBoundsOnScreen
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.launch
+
+object StatusBarOperatorNameViewBinder {
+    fun bind(
+        operatorFrameView: View,
+        viewModel: StatusBarOperatorNameViewModel,
+        areaTint: (Int) -> Flow<StatusBarTintColor>,
+    ) {
+        operatorFrameView.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                val displayId = operatorFrameView.display.displayId
+
+                val operatorNameText =
+                    operatorFrameView.requireViewById<TextView>(R.id.operator_name)
+                launch { viewModel.operatorName.collect { operatorNameText.text = it } }
+
+                launch {
+                    val tint = areaTint(displayId)
+                    tint.collect { statusBarTintColors ->
+                        operatorNameText.setTextColor(
+                            statusBarTintColors.tint(operatorNameText.viewBoundsOnScreen())
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
index 5614d82..ebf4391 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/composable/StatusBarRoot.kt
@@ -44,6 +44,7 @@
 import com.android.systemui.statusbar.phone.ongoingcall.StatusBarChipsModernization
 import com.android.systemui.statusbar.phone.ui.DarkIconManager
 import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarIconBlockListBinder
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.HomeStatusBarViewBinder
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel
@@ -150,6 +151,11 @@
                             darkIconDispatcher,
                         )
                     iconController.addIconGroup(darkIconManager)
+                    HomeStatusBarIconBlockListBinder.bind(
+                        statusIconContainer,
+                        darkIconManager,
+                        statusBarViewModel.iconBlockList,
+                    )
 
                     if (!StatusBarChipsModernization.isEnabled) {
                         ongoingCallController.setChipView(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
index 6e9e1ec..7f9a80b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModel.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
+import android.annotation.ColorInt
+import android.graphics.Rect
 import android.view.View
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -27,6 +29,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
 import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.plugins.DarkIconDispatcher
 import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -43,8 +46,10 @@
 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
 import com.android.systemui.statusbar.notification.headsup.PinnedStatus
 import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.phone.domain.interactor.DarkIconInteractor
 import com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor
-import com.android.systemui.statusbar.pipeline.shared.domain.interactor.CollapsedStatusBarInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.HomeStatusBarIconBlockListInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.HomeStatusBarInteractor
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -52,6 +57,7 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.conflate
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.flow.filter
@@ -90,6 +96,9 @@
      */
     val ongoingActivityChips: StateFlow<MultipleOngoingActivityChipsModel>
 
+    /** View model for the carrier name that may show in the status bar based on carrier config */
+    val operatorNameViewModel: StatusBarOperatorNameViewModel
+
     /**
      * True if the current scene can show the home status bar (aka this status bar), and false if
      * the current scene should never show the home status bar.
@@ -99,6 +108,8 @@
      */
     val isHomeStatusBarAllowedByScene: StateFlow<Boolean>
 
+    /** True if the operator name view is not hidden due to HUN or other visibility state */
+    val shouldShowOperatorNameView: Flow<Boolean>
     val isClockVisible: Flow<VisibilityModel>
     val isNotificationIconContainerVisible: Flow<VisibilityModel>
     /**
@@ -108,6 +119,9 @@
      */
     val systemInfoCombinedVis: StateFlow<SystemInfoCombinedVisibilityModel>
 
+    /** Which icons to block from the home status bar */
+    val iconBlockList: Flow<List<String>>
+
     /**
      * Apps can request a low profile mode [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE] where
      * status bar and navigation icons dim. In this mode, a notification dot appears where the
@@ -119,6 +133,12 @@
      */
     fun areNotificationsLightsOut(displayId: Int): Flow<Boolean>
 
+    /**
+     * Given a displayId, returns a flow of [StatusBarTintColor], a functional interface that will
+     * allow a view to calculate its correct tint depending on location
+     */
+    fun areaTint(displayId: Int): Flow<StatusBarTintColor>
+
     /** Models the current visibility for a specific child view of status bar. */
     data class VisibilityModel(
         @View.Visibility val visibility: Int,
@@ -137,12 +157,15 @@
 class HomeStatusBarViewModelImpl
 @Inject
 constructor(
-    collapsedStatusBarInteractor: CollapsedStatusBarInteractor,
+    homeStatusBarInteractor: HomeStatusBarInteractor,
+    homeStatusBarIconBlockListInteractor: HomeStatusBarIconBlockListInteractor,
     private val lightsOutInteractor: LightsOutInteractor,
     private val notificationsInteractor: ActiveNotificationsInteractor,
+    private val darkIconInteractor: DarkIconInteractor,
     headsUpNotificationInteractor: HeadsUpNotificationInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
     keyguardInteractor: KeyguardInteractor,
+    override val operatorNameViewModel: StatusBarOperatorNameViewModel,
     sceneInteractor: SceneInteractor,
     sceneContainerOcclusionInteractor: SceneContainerOcclusionInteractor,
     shadeInteractor: ShadeInteractor,
@@ -192,6 +215,21 @@
                 .distinctUntilChanged()
         }
 
+    override fun areaTint(displayId: Int): Flow<StatusBarTintColor> =
+        darkIconInteractor
+            .darkState(displayId)
+            .map { (areas: Collection<Rect>, tint: Int) ->
+                StatusBarTintColor { viewBounds: Rect ->
+                    if (DarkIconDispatcher.isInAreas(areas, viewBounds)) {
+                        tint
+                    } else {
+                        DarkIconDispatcher.DEFAULT_ICON_TINT
+                    }
+                }
+            }
+            .conflate()
+            .distinctUntilChanged()
+
     /**
      * True if the current SysUI state can show the home status bar (aka this status bar), and false
      * if we shouldn't be showing any part of the home status bar.
@@ -233,11 +271,25 @@
             primaryOngoingActivityChip.map { it is OngoingActivityChipModel.Shown }
         }
 
+    override val shouldShowOperatorNameView: Flow<Boolean> =
+        combine(
+            shouldHomeStatusBarBeVisible,
+            headsUpNotificationInteractor.statusBarHeadsUpState,
+            homeStatusBarInteractor.visibilityViaDisableFlags,
+            homeStatusBarInteractor.shouldShowOperatorName,
+        ) { shouldStatusBarBeVisible, headsUpState, visibilityViaDisableFlags, shouldShowOperator ->
+            val hideForHeadsUp = headsUpState == PinnedStatus.PinnedBySystem
+            shouldStatusBarBeVisible &&
+                !hideForHeadsUp &&
+                visibilityViaDisableFlags.isSystemInfoAllowed &&
+                shouldShowOperator
+        }
+
     override val isClockVisible: Flow<VisibilityModel> =
         combine(
             shouldHomeStatusBarBeVisible,
             headsUpNotificationInteractor.statusBarHeadsUpState,
-            collapsedStatusBarInteractor.visibilityViaDisableFlags,
+            homeStatusBarInteractor.visibilityViaDisableFlags,
         ) { shouldStatusBarBeVisible, headsUpState, visibilityViaDisableFlags ->
             val hideClockForHeadsUp = headsUpState == PinnedStatus.PinnedBySystem
             val showClock =
@@ -252,7 +304,7 @@
         combine(
             shouldHomeStatusBarBeVisible,
             isAnyChipVisible,
-            collapsedStatusBarInteractor.visibilityViaDisableFlags,
+            homeStatusBarInteractor.visibilityViaDisableFlags,
         ) { shouldStatusBarBeVisible, anyChipVisible, visibilityViaDisableFlags ->
             val showNotificationIconContainer =
                 if (anyChipVisible) {
@@ -268,10 +320,9 @@
         }
 
     private val isSystemInfoVisible =
-        combine(
-            shouldHomeStatusBarBeVisible,
-            collapsedStatusBarInteractor.visibilityViaDisableFlags,
-        ) { shouldStatusBarBeVisible, visibilityViaDisableFlags ->
+        combine(shouldHomeStatusBarBeVisible, homeStatusBarInteractor.visibilityViaDisableFlags) {
+            shouldStatusBarBeVisible,
+            visibilityViaDisableFlags ->
             val showSystemInfo =
                 shouldStatusBarBeVisible && visibilityViaDisableFlags.isSystemInfoAllowed
             VisibilityModel(showSystemInfo.toVisibleOrGone(), visibilityViaDisableFlags.animate)
@@ -293,6 +344,9 @@
                 ),
             )
 
+    override val iconBlockList: Flow<List<String>> =
+        homeStatusBarIconBlockListInteractor.iconBlockList
+
     @View.Visibility
     private fun Boolean.toVisibleOrGone(): Int {
         return if (this) View.VISIBLE else View.GONE
@@ -302,3 +356,8 @@
     @View.Visibility
     private fun Boolean.toVisibleOrInvisible(): Int = if (this) View.VISIBLE else View.INVISIBLE
 }
+
+/** Lookup the color for a given view in the status bar */
+fun interface StatusBarTintColor {
+    @ColorInt fun tint(viewBounds: Rect): Int
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt
new file mode 100644
index 0000000..7ae74c3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModel.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flatMapLatest
+
+/**
+ * View model for the operator name (aka carrier name) of the carrier for the default data
+ * subscription.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class StatusBarOperatorNameViewModel
+@Inject
+constructor(mobileIconsInteractor: MobileIconsInteractor) {
+    val operatorName: Flow<String?> =
+        mobileIconsInteractor.defaultDataSubId.flatMapLatest {
+            mobileIconsInteractor.getMobileConnectionInteractorForSubId(it).carrierName
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index af6e8a0..b6e01e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -18,15 +18,15 @@
 
 import android.os.Bundle
 import androidx.annotation.VisibleForTesting
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.demomode.DemoMode
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -62,7 +62,7 @@
     private val realImpl: RealWifiRepository,
     private val demoImpl: DemoWifiRepository,
     private val demoModeController: DemoModeController,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
 ) : WifiRepository {
     private val isDemoMode =
         conflatedCallbackFlow {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index fa243da..f9556d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -19,7 +19,7 @@
 import android.content.Context
 import com.android.systemui.Flags.statusBarStaticInoutIndicators
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.log.table.TableLogBuffer
 import com.android.systemui.log.table.logDiffsForTable
 import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
@@ -63,7 +63,7 @@
     private val context: Context,
     @WifiTableLog wifiTableLogBuffer: TableLogBuffer,
     interactor: WifiInteractor,
-    @Application private val scope: CoroutineScope,
+    @Background scope: CoroutineScope,
     wifiConstants: WifiConstants,
 ) : WifiViewModelCommon {
     override val wifiIcon: StateFlow<WifiIcon> =
@@ -89,15 +89,11 @@
                     else -> WifiIcon.Hidden
                 }
             }
-            .logDiffsForTable(
-                wifiTableLogBuffer,
-                columnPrefix = "",
-                initialValue = WifiIcon.Hidden,
-            )
+            .logDiffsForTable(wifiTableLogBuffer, columnPrefix = "", initialValue = WifiIcon.Hidden)
             .stateIn(
                 scope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = WifiIcon.Hidden
+                initialValue = WifiIcon.Hidden,
             )
 
     /** The wifi activity status. Null if we shouldn't display the activity status. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
index a3dcc3b..ece5a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.media.projection.StopReason;
 import com.android.systemui.Dumpable;
 import com.android.systemui.statusbar.policy.CastController.Callback;
 
@@ -26,7 +27,7 @@
     void setCurrentUserId(int currentUserId);
     List<CastDevice> getCastDevices();
     void startCasting(CastDevice device);
-    void stopCasting(CastDevice device);
+    void stopCasting(CastDevice device, @StopReason int stopReason);
 
     /**
      * @return whether we have a connected device.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 52f80fb..ab20850 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -185,13 +185,13 @@
     }
 
     @Override
-    public void stopCasting(CastDevice device) {
+    public void stopCasting(CastDevice device, @StopReason int stopReason) {
         final boolean isProjection = device.getTag() instanceof MediaProjectionInfo;
         mLogger.logStopCasting(isProjection);
         if (isProjection) {
             final MediaProjectionInfo projection = (MediaProjectionInfo) device.getTag();
             if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) {
-                mProjectionManager.stopActiveProjection(StopReason.STOP_QS_TILE);
+                mProjectionManager.stopActiveProjection(stopReason);
             } else {
                 mLogger.logStopCastingNoProjection(projection);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 78954de..b966005 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -32,16 +32,13 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.KeyguardConstants;
-import com.android.keyguard.KeyguardVisibilityHelper;
 import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
 import com.android.settingslib.drawable.CircleFramedDrawable;
 import com.android.systemui.animation.Expandable;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.user.UserSwitchDialogController;
 import com.android.systemui.res.R;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -57,6 +54,7 @@
 
 /**
  * Manages the user switch on the Keyguard that is used for opening the QS user panel.
+ * TODO: b/384064264 - Move to blueprint sections
  */
 @KeyguardUserSwitcherScope
 public class KeyguardQsUserSwitchController extends ViewController<FrameLayout> {
@@ -73,9 +71,7 @@
     private BaseUserSwitcherAdapter mAdapter;
     private final KeyguardStateController mKeyguardStateController;
     private final FalsingManager mFalsingManager;
-    protected final SysuiStatusBarStateController mStatusBarStateController;
     private final ConfigurationController mConfigurationController;
-    private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
     private final UserSwitchDialogController mUserSwitchDialogController;
     private final UiEventLogger mUiEventLogger;
     @VisibleForTesting
@@ -84,26 +80,6 @@
     UserRecord mCurrentUser;
     private boolean mIsKeyguardShowing;
 
-    // State info for the user switch and keyguard
-    private int mBarState;
-
-    private final StatusBarStateController.StateListener mStatusBarStateListener =
-            new StatusBarStateController.StateListener() {
-                @Override
-                public void onStateChanged(int newState) {
-                    boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
-                    boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
-                    int oldState = mBarState;
-                    mBarState = newState;
-
-                    setKeyguardQsUserSwitchVisibility(
-                            newState,
-                            keyguardFadingAway,
-                            goingToFullShade,
-                            oldState);
-                }
-            };
-
     private ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
 
@@ -144,7 +120,6 @@
             KeyguardStateController keyguardStateController,
             FalsingManager falsingManager,
             ConfigurationController configurationController,
-            SysuiStatusBarStateController statusBarStateController,
             DozeParameters dozeParameters,
             ScreenOffAnimationController screenOffAnimationController,
             UserSwitchDialogController userSwitchDialogController,
@@ -157,11 +132,6 @@
         mKeyguardStateController = keyguardStateController;
         mFalsingManager = falsingManager;
         mConfigurationController = configurationController;
-        mStatusBarStateController = statusBarStateController;
-        mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
-                keyguardStateController, dozeParameters,
-                screenOffAnimationController,  /* animateYPos= */ false,
-                /* logBuffer= */ null);
         mUserSwitchDialogController = userSwitchDialogController;
         mUiEventLogger = uiEventLogger;
     }
@@ -184,15 +154,12 @@
             if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                 return;
             }
-            if (isListAnimating()) {
-                return;
-            }
 
             // Tapping anywhere in the view will open the user switcher
             mUiEventLogger.log(
                     LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP);
 
-            mUserSwitchDialogController.showDialog(mUserAvatarViewWithBackground.getContext(),
+            mUserSwitchDialogController.showDialog(
                     Expandable.fromView(mUserAvatarViewWithBackground));
         });
 
@@ -212,7 +179,6 @@
         if (DEBUG) Log.d(TAG, "onViewAttached");
         mAdapter.registerDataSetObserver(mDataSetObserver);
         mDataSetObserver.onChanged();
-        mStatusBarStateController.addCallback(mStatusBarStateListener);
         mConfigurationController.addCallback(mConfigurationListener);
         mKeyguardStateController.addCallback(mKeyguardStateCallback);
         // Force update when view attached in case configuration changed while the view was detached
@@ -225,7 +191,6 @@
         if (DEBUG) Log.d(TAG, "onViewDetached");
 
         mAdapter.unregisterDataSetObserver(mDataSetObserver);
-        mStatusBarStateController.removeCallback(mStatusBarStateListener);
         mConfigurationController.removeCallback(mConfigurationListener);
         mKeyguardStateController.removeCallback(mKeyguardStateCallback);
     }
@@ -333,18 +298,6 @@
     }
 
     /**
-     * Set the visibility of the user avatar view based on some new state.
-     */
-    public void setKeyguardQsUserSwitchVisibility(
-            int statusBarState,
-            boolean keyguardFadingAway,
-            boolean goingToFullShade,
-            int oldStatusBarState) {
-        mKeyguardVisibilityHelper.setViewVisibility(
-                statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
-    }
-
-    /**
      * Update position of the view with an optional animation
      */
     public void updatePosition(int x, int y, boolean animate) {
@@ -357,12 +310,6 @@
      * Set keyguard user avatar view alpha.
      */
     public void setAlpha(float alpha) {
-        if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
-            mView.setAlpha(alpha);
-        }
-    }
-
-    private boolean isListAnimating() {
-        return mKeyguardVisibilityHelper.isVisibilityAnimating();
+        mView.setAlpha(alpha);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
deleted file mode 100644
index 3eeb59d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-
-import androidx.core.graphics.ColorUtils;
-
-import com.android.app.animation.Interpolators;
-import com.android.keyguard.KeyguardConstants;
-import com.android.systemui.qs.tiles.UserDetailItemView;
-import com.android.systemui.res.R;
-
-/**
- * Displays a user on the keyguard user switcher.
- */
-public class KeyguardUserDetailItemView extends UserDetailItemView {
-
-    private static final String TAG = "KeyguardUserDetailItemView";
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-
-    private static final int ANIMATION_DURATION_FADE_NAME = 240;
-
-    private float mDarkAmount;
-    private int mTextColor;
-
-    public KeyguardUserDetailItemView(Context context) {
-        this(context, null);
-    }
-
-    public KeyguardUserDetailItemView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public KeyguardUserDetailItemView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public KeyguardUserDetailItemView(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    @Override
-    protected int getFontSizeDimen() {
-        return R.dimen.kg_user_switcher_text_size;
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mTextColor = mName.getCurrentTextColor();
-        updateDark();
-    }
-
-    /**
-     * Update visibility of this view.
-     *
-     * @param showItem If true, this item is visible on the screen to the user. Generally this
-     *                 means that the item would be clickable. If false, item visibility will be
-     *                 set to GONE and hidden entirely.
-     * @param showTextName Whether or not the name should be shown next to the icon. If false,
-     *                     only the icon is shown.
-     * @param animate Whether the transition should be animated. Note, this only applies to
-     *                animating the text name. The item itself will not animate (i.e. fade in/out).
-     *                Instead, we delegate that to the parent view.
-     */
-    void updateVisibilities(boolean showItem, boolean showTextName, boolean animate) {
-        if (DEBUG) {
-            Log.d(TAG, String.format("updateVisibilities itemIsShown=%b nameIsShown=%b animate=%b",
-                    showItem, showTextName, animate));
-        }
-
-        getBackground().setAlpha((showItem && showTextName) ? 255 : 0);
-
-        if (showItem) {
-            if (showTextName) {
-                mName.setVisibility(View.VISIBLE);
-                if (animate) {
-                    mName.setAlpha(0f);
-                    mName.animate()
-                            .alpha(1f)
-                            .setDuration(ANIMATION_DURATION_FADE_NAME)
-                            .setInterpolator(Interpolators.ALPHA_IN);
-                } else {
-                    mName.setAlpha(1f);
-                }
-            } else {
-                if (animate) {
-                    mName.setVisibility(View.VISIBLE);
-                    mName.setAlpha(1f);
-                    mName.animate()
-                            .alpha(0f)
-                            .setDuration(ANIMATION_DURATION_FADE_NAME)
-                            .setInterpolator(Interpolators.ALPHA_OUT)
-                            .withEndAction(() -> {
-                                mName.setVisibility(View.GONE);
-                                mName.setAlpha(1f);
-                            });
-                } else {
-                    mName.setVisibility(View.GONE);
-                    mName.setAlpha(1f);
-                }
-            }
-            setVisibility(View.VISIBLE);
-            setAlpha(1f);
-        } else {
-            // If item isn't shown, don't animate. The parent class will animate the view instead
-            setVisibility(View.GONE);
-            setAlpha(1f);
-            mName.setVisibility(showTextName ? View.VISIBLE : View.GONE);
-            mName.setAlpha(1f);
-        }
-    }
-
-    /**
-     * Set the amount (ratio) that the device has transitioned to doze.
-     *
-     * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
-     */
-    public void setDarkAmount(float darkAmount) {
-        if (mDarkAmount == darkAmount) {
-            return;
-        }
-        mDarkAmount = darkAmount;
-        updateDark();
-    }
-
-    private void updateDark() {
-        final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
-        mName.setTextColor(blendedTextColor);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
deleted file mode 100644
index 770f441..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.database.DataSetObserver;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.os.UserHandle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.app.animation.Interpolators;
-import com.android.keyguard.KeyguardConstants;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.keyguard.KeyguardVisibilityHelper;
-import com.android.keyguard.dagger.KeyguardUserSwitcherScope;
-import com.android.settingslib.drawable.CircleFramedDrawable;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.user.data.source.UserRecord;
-import com.android.systemui.util.ViewController;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-/**
- * Manages the user switcher on the Keyguard.
- */
-@KeyguardUserSwitcherScope
-@Deprecated
-public class KeyguardUserSwitcherController extends ViewController<KeyguardUserSwitcherView> {
-
-    private static final String TAG = "KeyguardUserSwitcherController";
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-
-    private static final AnimationProperties ANIMATION_PROPERTIES =
-            new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-
-    private final Context mContext;
-    private final UserSwitcherController mUserSwitcherController;
-    private final ScreenLifecycle mScreenLifecycle;
-    private final KeyguardUserAdapter mAdapter;
-    private final KeyguardStateController mKeyguardStateController;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    protected final SysuiStatusBarStateController mStatusBarStateController;
-    private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
-    private ObjectAnimator mBgAnimator;
-    private final KeyguardUserSwitcherScrim mBackground;
-
-    // Child views of KeyguardUserSwitcherView
-    private KeyguardUserSwitcherListView mListView;
-
-    // State info for the user switcher
-    private boolean mUserSwitcherOpen;
-    private int mCurrentUserId = UserHandle.USER_NULL;
-    private int mBarState;
-    private float mDarkAmount;
-
-    private final KeyguardUpdateMonitorCallback mInfoCallback =
-            new KeyguardUpdateMonitorCallback() {
-                @Override
-                public void onKeyguardVisibilityChanged(boolean visible) {
-                    if (DEBUG) Log.d(TAG, String.format("onKeyguardVisibilityChanged %b", visible));
-                    // Any time the keyguard is hidden, try to close the user switcher menu to
-                    // restore keyguard to the default state
-                    if (!visible) {
-                        closeSwitcherIfOpenAndNotSimple(false);
-                    }
-                }
-
-                @Override
-                public void onUserSwitching(int userId) {
-                    closeSwitcherIfOpenAndNotSimple(false);
-                }
-            };
-
-    private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
-        @Override
-        public void onScreenTurnedOff() {
-            if (DEBUG) Log.d(TAG, "onScreenTurnedOff");
-            closeSwitcherIfOpenAndNotSimple(false);
-        }
-    };
-
-    private final StatusBarStateController.StateListener mStatusBarStateListener =
-            new StatusBarStateController.StateListener() {
-                @Override
-                public void onStateChanged(int newState) {
-                    if (DEBUG) Log.d(TAG, String.format("onStateChanged: newState=%d", newState));
-
-                    boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
-                    boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
-                    int oldState = mBarState;
-                    mBarState = newState;
-
-                    if (mStatusBarStateController.goingToFullShade()
-                            || mKeyguardStateController.isKeyguardFadingAway()) {
-                        closeSwitcherIfOpenAndNotSimple(true);
-                    }
-
-                    setKeyguardUserSwitcherVisibility(
-                            newState,
-                            keyguardFadingAway,
-                            goingToFullShade,
-                            oldState);
-                }
-
-                @Override
-                public void onDozeAmountChanged(float linearAmount, float amount) {
-                    if (DEBUG) {
-                        Log.d(TAG, String.format("onDozeAmountChanged: linearAmount=%f amount=%f",
-                                linearAmount, amount));
-                    }
-                    setDarkAmount(amount);
-                }
-            };
-
-    @Inject
-    public KeyguardUserSwitcherController(
-            KeyguardUserSwitcherView keyguardUserSwitcherView,
-            Context context,
-            @Main Resources resources,
-            LayoutInflater layoutInflater,
-            ScreenLifecycle screenLifecycle,
-            UserSwitcherController userSwitcherController,
-            KeyguardStateController keyguardStateController,
-            SysuiStatusBarStateController statusBarStateController,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            DozeParameters dozeParameters,
-            ScreenOffAnimationController screenOffAnimationController) {
-        super(keyguardUserSwitcherView);
-        if (DEBUG) Log.d(TAG, "New KeyguardUserSwitcherController");
-        mContext = context;
-        mScreenLifecycle = screenLifecycle;
-        mUserSwitcherController = userSwitcherController;
-        mKeyguardStateController = keyguardStateController;
-        mStatusBarStateController = statusBarStateController;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mAdapter = new KeyguardUserAdapter(mContext, resources, layoutInflater,
-                mUserSwitcherController, this);
-        mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
-                keyguardStateController, dozeParameters,
-                screenOffAnimationController, /* animateYPos= */ false,
-                /* logBuffer= */ null);
-        mBackground = new KeyguardUserSwitcherScrim(context);
-    }
-
-    @Override
-    protected void onInit() {
-        super.onInit();
-
-        if (DEBUG) Log.d(TAG, "onInit");
-
-        mListView = mView.findViewById(R.id.keyguard_user_switcher_list);
-
-        mView.setOnTouchListener((v, event) -> {
-            if (!isListAnimating()) {
-                // Hide switcher if it didn't handle the touch event (and block the event from
-                // going through).
-                return closeSwitcherIfOpenAndNotSimple(true);
-            }
-            return false;
-        });
-    }
-
-    @Override
-    protected void onViewAttached() {
-        if (DEBUG) Log.d(TAG, "onViewAttached");
-        mAdapter.registerDataSetObserver(mDataSetObserver);
-        mAdapter.notifyDataSetChanged();
-        mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
-        mStatusBarStateController.addCallback(mStatusBarStateListener);
-        mScreenLifecycle.addObserver(mScreenObserver);
-        if (isSimpleUserSwitcher()) {
-            // Don't use the background for the simple user switcher
-            setUserSwitcherOpened(true /* open */, true /* animate */);
-        } else {
-            mView.addOnLayoutChangeListener(mBackground);
-            mView.setBackground(mBackground);
-            mBackground.setAlpha(0);
-        }
-    }
-
-    @Override
-    protected void onViewDetached() {
-        if (DEBUG) Log.d(TAG, "onViewDetached");
-
-        // Detaching the view will always close the switcher
-        closeSwitcherIfOpenAndNotSimple(false);
-
-        mAdapter.unregisterDataSetObserver(mDataSetObserver);
-        mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
-        mStatusBarStateController.removeCallback(mStatusBarStateListener);
-        mScreenLifecycle.removeObserver(mScreenObserver);
-        mView.removeOnLayoutChangeListener(mBackground);
-        mView.setBackground(null);
-        mBackground.setAlpha(0);
-    }
-
-    /**
-     * Returns {@code true} if the user switcher should be open by default on the lock screen.
-     *
-     * @see android.os.UserManager#isUserSwitcherEnabled()
-     */
-    public boolean isSimpleUserSwitcher() {
-        return mUserSwitcherController.isSimpleUserSwitcher();
-    }
-
-    public int getHeight() {
-        return mListView.getHeight();
-    }
-
-    /**
-     * @param animate if the transition should be animated
-     * @return true if the switcher state changed
-     */
-    public boolean closeSwitcherIfOpenAndNotSimple(boolean animate) {
-        if (isUserSwitcherOpen() && !isSimpleUserSwitcher()) {
-            setUserSwitcherOpened(false /* open */, animate);
-            return true;
-        }
-        return false;
-    }
-
-    public final DataSetObserver mDataSetObserver = new DataSetObserver() {
-        @Override
-        public void onChanged() {
-            refreshUserList();
-        }
-    };
-
-    void refreshUserList() {
-        final int childCount = mListView.getChildCount();
-        final int adapterCount = mAdapter.getCount();
-        final int count = Math.max(childCount, adapterCount);
-
-        if (DEBUG) {
-            Log.d(TAG, String.format("refreshUserList childCount=%d adapterCount=%d", childCount,
-                    adapterCount));
-        }
-
-        boolean foundCurrentUser = false;
-        for (int i = 0; i < count; i++) {
-            if (i < adapterCount) {
-                View oldView = null;
-                if (i < childCount) {
-                    oldView = mListView.getChildAt(i);
-                }
-                KeyguardUserDetailItemView newView = (KeyguardUserDetailItemView)
-                        mAdapter.getView(i, oldView, mListView);
-                UserRecord userTag =
-                        (UserRecord) newView.getTag();
-                if (userTag.isCurrent) {
-                    if (i != 0) {
-                        Log.w(TAG, "Current user is not the first view in the list");
-                    }
-                    foundCurrentUser = true;
-                    mCurrentUserId = userTag.info.id;
-                    // Current user is always visible
-                    newView.updateVisibilities(true /* showItem */,
-                            mUserSwitcherOpen /* showTextName */, false /* animate */);
-                } else {
-                    // Views for non-current users are always expanded (e.g. they should the name
-                    // next to the user icon). However, they could be hidden entirely if the list
-                    // is closed.
-                    newView.updateVisibilities(mUserSwitcherOpen /* showItem */,
-                            true /* showTextName */, false /* animate */);
-                }
-                newView.setDarkAmount(mDarkAmount);
-                if (oldView == null) {
-                    // We ran out of existing views. Add it at the end.
-                    mListView.addView(newView);
-                } else if (oldView != newView) {
-                    // We couldn't rebind the view. Replace it.
-                    mListView.replaceView(newView, i);
-                }
-            } else {
-                mListView.removeLastView();
-            }
-        }
-        if (!foundCurrentUser) {
-            Log.w(TAG, "Current user is not listed");
-            mCurrentUserId = UserHandle.USER_NULL;
-        }
-    }
-
-    /**
-     * Set the visibility of the keyguard user switcher view based on some new state.
-     */
-    public void setKeyguardUserSwitcherVisibility(
-            int statusBarState,
-            boolean keyguardFadingAway,
-            boolean goingToFullShade,
-            int oldStatusBarState) {
-        mKeyguardVisibilityHelper.setViewVisibility(
-                statusBarState, keyguardFadingAway, goingToFullShade, oldStatusBarState);
-    }
-
-    /**
-     * Update position of the view with an optional animation
-     */
-    public void updatePosition(int x, int y, boolean animate) {
-        PropertyAnimator.setProperty(mListView, AnimatableProperty.Y, y, ANIMATION_PROPERTIES,
-                animate);
-        PropertyAnimator.setProperty(mListView, AnimatableProperty.TRANSLATION_X, -Math.abs(x),
-                ANIMATION_PROPERTIES, animate);
-
-        Rect r = new Rect();
-        mListView.getDrawingRect(r);
-        mView.offsetDescendantRectToMyCoords(mListView, r);
-        mBackground.setGradientCenter(
-                (int) (mListView.getTranslationX() + r.left + r.width() / 2),
-                (int) (mListView.getTranslationY() + r.top + r.height() / 2));
-    }
-
-    /**
-     * Set keyguard user switcher view alpha.
-     */
-    public void setAlpha(float alpha) {
-        if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
-            mView.setAlpha(alpha);
-        }
-    }
-
-    /**
-     * Set the amount (ratio) that the device has transitioned to doze.
-     *
-     * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
-     */
-    private void setDarkAmount(float darkAmount) {
-        boolean isFullyDozed = darkAmount == 1;
-        if (darkAmount == mDarkAmount) {
-            return;
-        }
-        mDarkAmount = darkAmount;
-        mListView.setDarkAmount(darkAmount);
-        if (isFullyDozed) {
-            closeSwitcherIfOpenAndNotSimple(false);
-        }
-    }
-
-    private boolean isListAnimating() {
-        return mKeyguardVisibilityHelper.isVisibilityAnimating() || mListView.isAnimating();
-    }
-
-    /**
-     * NOTE: switcher state is updated before animations finish.
-     *
-     * @param animate true to animate transition. The user switcher state (i.e.
-     *                {@link #isUserSwitcherOpen()}) is updated before animation is finished.
-     */
-    private void setUserSwitcherOpened(boolean open, boolean animate) {
-        if (DEBUG) {
-            Log.d(TAG,
-                    String.format("setUserSwitcherOpened: %b -> %b (animate=%b)",
-                            mUserSwitcherOpen, open, animate));
-        }
-        mUserSwitcherOpen = open;
-        updateVisibilities(animate);
-    }
-
-    private void updateVisibilities(boolean animate) {
-        if (DEBUG) Log.d(TAG, String.format("updateVisibilities: animate=%b", animate));
-        if (mBgAnimator != null) {
-            mBgAnimator.cancel();
-        }
-
-        if (mUserSwitcherOpen) {
-            mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
-            mBgAnimator.setDuration(400);
-            mBgAnimator.setInterpolator(Interpolators.ALPHA_IN);
-            mBgAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mBgAnimator = null;
-                }
-            });
-            mBgAnimator.start();
-        } else {
-            mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 255, 0);
-            mBgAnimator.setDuration(400);
-            mBgAnimator.setInterpolator(Interpolators.ALPHA_OUT);
-            mBgAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mBgAnimator = null;
-                }
-            });
-            mBgAnimator.start();
-        }
-        mListView.updateVisibilities(mUserSwitcherOpen, animate);
-    }
-
-    private boolean isUserSwitcherOpen() {
-        return mUserSwitcherOpen;
-    }
-
-    static class KeyguardUserAdapter extends
-            BaseUserSwitcherAdapter implements View.OnClickListener {
-
-        private final Context mContext;
-        private final Resources mResources;
-        private final LayoutInflater mLayoutInflater;
-        private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
-        private View mCurrentUserView;
-        // List of users where the first entry is always the current user
-        private ArrayList<UserRecord> mUsersOrdered = new ArrayList<>();
-
-        KeyguardUserAdapter(Context context, Resources resources, LayoutInflater layoutInflater,
-                UserSwitcherController controller,
-                KeyguardUserSwitcherController keyguardUserSwitcherController) {
-            super(controller);
-            mContext = context;
-            mResources = resources;
-            mLayoutInflater = layoutInflater;
-            mKeyguardUserSwitcherController = keyguardUserSwitcherController;
-        }
-
-        @Override
-        public void notifyDataSetChanged() {
-            // At this point, value of isSimpleUserSwitcher() may have changed in addition to the
-            // data set
-            refreshUserOrder();
-            super.notifyDataSetChanged();
-        }
-
-        void refreshUserOrder() {
-            List<UserRecord> users = super.getUsers();
-            mUsersOrdered = new ArrayList<>(users.size());
-            for (int i = 0; i < users.size(); i++) {
-                UserRecord record = users.get(i);
-                if (record.isCurrent) {
-                    mUsersOrdered.add(0, record);
-                } else {
-                    mUsersOrdered.add(record);
-                }
-            }
-        }
-
-        @Override
-        protected ArrayList<UserRecord> getUsers() {
-            return mUsersOrdered;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            UserRecord item = getItem(position);
-            return createUserDetailItemView(convertView, parent, item);
-        }
-
-        KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) {
-            if (!(convertView instanceof KeyguardUserDetailItemView)
-                    || !(convertView.getTag() instanceof UserRecord)) {
-                convertView = mLayoutInflater.inflate(
-                        R.layout.keyguard_user_switcher_item, parent, false);
-            }
-            return (KeyguardUserDetailItemView) convertView;
-        }
-
-        KeyguardUserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
-                UserRecord item) {
-            KeyguardUserDetailItemView v = convertOrInflate(convertView, parent);
-            v.setOnClickListener(this);
-
-            String name = getName(mContext, item);
-            if (item.picture == null) {
-                v.bind(name, getDrawable(item).mutate(), item.resolveId());
-            } else {
-                int avatarSize =
-                        (int) mResources.getDimension(R.dimen.kg_framed_avatar_size);
-                Drawable drawable = new CircleFramedDrawable(item.picture, avatarSize);
-                drawable.setColorFilter(
-                        item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
-                v.bind(name, drawable, item.info.id);
-            }
-            v.setActivated(item.isCurrent);
-            v.setDisabledByAdmin(item.isDisabledByAdmin());
-            v.setEnabled(item.isSwitchToEnabled);
-            UserSwitcherController.setSelectableAlpha(v);
-
-            if (item.isCurrent) {
-                mCurrentUserView = v;
-            }
-            v.setTag(item);
-            return v;
-        }
-
-        private Drawable getDrawable(UserRecord item) {
-            Drawable drawable;
-            if (item.isCurrent && item.isGuest) {
-                drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
-            } else {
-                drawable = getIconDrawable(mContext, item);
-            }
-
-            int iconColorRes;
-            if (item.isSwitchToEnabled) {
-                iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
-            } else {
-                iconColorRes = R.color.kg_user_switcher_restricted_avatar_icon_color;
-            }
-            drawable.setTint(mResources.getColor(iconColorRes, mContext.getTheme()));
-
-            Drawable bg = mContext.getDrawable(com.android.settingslib.R.drawable.user_avatar_bg);
-            drawable = new LayerDrawable(new Drawable[]{bg, drawable});
-            return drawable;
-        }
-
-        @Override
-        public void onClick(View v) {
-            UserRecord user = (UserRecord) v.getTag();
-
-            if (mKeyguardUserSwitcherController.isListAnimating()) {
-                return;
-            }
-
-            if (mKeyguardUserSwitcherController.isUserSwitcherOpen()) {
-                if (!user.isCurrent || user.isGuest) {
-                    onUserListItemClicked(user);
-                } else {
-                    mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(
-                            true /* animate */);
-                }
-            } else {
-                // If switcher is closed, tapping anywhere in the view will open it
-                mKeyguardUserSwitcherController.setUserSwitcherOpened(
-                        true /* open */, true /* animate */);
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
deleted file mode 100644
index 363b06a..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherListView.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-
-import com.android.app.animation.Interpolators;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
-import com.android.keyguard.KeyguardConstants;
-import com.android.settingslib.animation.AppearAnimationUtils;
-import com.android.settingslib.animation.DisappearAnimationUtils;
-
-/**
- * The container for the user switcher on Keyguard.
- */
-public class KeyguardUserSwitcherListView extends AlphaOptimizedLinearLayout {
-
-    private static final String TAG = "KeyguardUserSwitcherListView";
-    private static final boolean DEBUG = KeyguardConstants.DEBUG;
-
-    private boolean mAnimating;
-    private final AppearAnimationUtils mAppearAnimationUtils;
-    private final DisappearAnimationUtils mDisappearAnimationUtils;
-
-    public KeyguardUserSwitcherListView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mAppearAnimationUtils = new AppearAnimationUtils(context,
-                AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
-                -0.5f /* translationScaleFactor */,
-                0.5f /* delayScaleFactor */,
-                Interpolators.FAST_OUT_SLOW_IN);
-        mDisappearAnimationUtils = new DisappearAnimationUtils(context,
-                AppearAnimationUtils.DEFAULT_APPEAR_DURATION,
-                0.2f /* translationScaleFactor */,
-                0.2f /* delayScaleFactor */,
-                Interpolators.FAST_OUT_SLOW_IN_REVERSE);
-    }
-
-    /**
-     * Set the amount (ratio) that the device has transitioned to doze.
-     *
-     * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
-     */
-    void setDarkAmount(float darkAmount) {
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View v = getChildAt(i);
-            if (v instanceof KeyguardUserDetailItemView) {
-                ((KeyguardUserDetailItemView) v).setDarkAmount(darkAmount);
-            }
-        }
-    }
-
-    boolean isAnimating() {
-        return mAnimating;
-    }
-
-    /**
-     * Update visibilities of this view and child views for when the user list is open or closed.
-     * If closed, this hides everything but the first item (which is always the current user).
-     */
-    void updateVisibilities(boolean open, boolean animate) {
-        if (DEBUG) {
-            Log.d(TAG, String.format("updateVisibilities: open=%b animate=%b childCount=%d",
-                    open, animate, getChildCount()));
-        }
-
-        mAnimating = false;
-
-        int childCount = getChildCount();
-        KeyguardUserDetailItemView[] userItemViews = new KeyguardUserDetailItemView[childCount];
-        for (int i = 0; i < childCount; i++) {
-            userItemViews[i] = (KeyguardUserDetailItemView) getChildAt(i);
-            userItemViews[i].clearAnimation();
-            if (i == 0) {
-                // The first child is always the current user.
-                userItemViews[i].updateVisibilities(true /* showItem */, open /* showTextName */,
-                        animate);
-                userItemViews[i].setClickable(true);
-            } else {
-                // Update clickable state immediately so that the menu feels more responsive
-                userItemViews[i].setClickable(open);
-                // when opening we need to make views visible beforehand so they can be animated
-                if (open) {
-                    userItemViews[i].updateVisibilities(true /* showItem */,
-                            true /* showTextName */, false /* animate */);
-                }
-
-            }
-        }
-
-        if (animate && userItemViews.length > 1) {
-            // AnimationUtils will immediately hide/show the first item in the array. Since the
-            // first view is the current user, we want to manage its visibility separately.
-            // Set first item to null so AnimationUtils ignores it.
-            userItemViews[0] = null;
-
-            setClipChildren(false);
-            setClipToPadding(false);
-            mAnimating = true;
-            (open ? mAppearAnimationUtils : mDisappearAnimationUtils)
-                    .startAnimation(userItemViews, () -> {
-                        setClipChildren(true);
-                        setClipToPadding(true);
-                        mAnimating = false;
-                        if (!open) {
-                            // after closing we hide children so that height of this view is correct
-                            for (int i = 1; i < userItemViews.length; i++) {
-                                userItemViews[i].updateVisibilities(false /* showItem */,
-                                        true /* showTextName */, false /* animate */);
-                            }
-                        }
-                    });
-        }
-    }
-
-    /**
-     * Replaces the view at the specified position in the group.
-     *
-     * @param index the position in the group of the view to remove
-     */
-    void replaceView(KeyguardUserDetailItemView newView, int index) {
-        removeViewAt(index);
-        addView(newView, index);
-    }
-
-    /**
-     * Removes the last view in the group.
-     */
-    void removeLastView() {
-        int lastIndex = getChildCount() - 1;
-        removeViewAt(lastIndex);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
deleted file mode 100644
index 5ed207cc3..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.RadialGradient;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-
-import com.android.systemui.res.R;
-
-/**
- * Gradient background for the user switcher on Keyguard.
- */
-public class KeyguardUserSwitcherScrim extends Drawable
-        implements View.OnLayoutChangeListener {
-
-    private static final float OUTER_EXTENT = 2.5f;
-    private static final float INNER_EXTENT = 0.25f;
-
-    private int mDarkColor;
-    private int mAlpha = 255;
-    private Paint mRadialGradientPaint = new Paint();
-    private int mCircleX;
-    private int mCircleY;
-    private int mSize;
-
-    public KeyguardUserSwitcherScrim(Context context) {
-        mDarkColor = context.getColor(
-                R.color.keyguard_user_switcher_background_gradient_color);
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        if (mAlpha == 0) {
-            return;
-        }
-        Rect bounds = getBounds();
-        canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.bottom, mRadialGradientPaint);
-    }
-
-    @Override
-    public void setAlpha(int alpha) {
-        mAlpha = alpha;
-        updatePaint();
-        invalidateSelf();
-    }
-
-    @Override
-    public int getAlpha() {
-        return mAlpha;
-    }
-
-    @Override
-    public void setColorFilter(ColorFilter colorFilter) {
-    }
-
-    @Override
-    public int getOpacity() {
-        return PixelFormat.TRANSLUCENT;
-    }
-
-    @Override
-    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
-            int oldTop, int oldRight, int oldBottom) {
-        if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
-            int width = right - left;
-            int height = bottom - top;
-            mSize = Math.max(width, height);
-            updatePaint();
-        }
-    }
-
-    private void updatePaint() {
-        if (mSize == 0) {
-            return;
-        }
-        float outerRadius = mSize * OUTER_EXTENT;
-        mRadialGradientPaint.setShader(
-                new RadialGradient(mCircleX, mCircleY, outerRadius,
-                        new int[] { Color.argb(
-                                        (int) (Color.alpha(mDarkColor) * mAlpha / 255f), 0, 0, 0),
-                                Color.TRANSPARENT },
-                        new float[] { Math.max(0f, INNER_EXTENT / OUTER_EXTENT), 1f },
-                        Shader.TileMode.CLAMP));
-    }
-
-    /**
-     * Sets the center of the radial gradient used as a background
-     *
-     * @param x
-     * @param y
-     */
-    public void setGradientCenter(int x, int y) {
-        mCircleX = x;
-        mCircleY = y;
-        updatePaint();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherView.java
deleted file mode 100644
index 3f0e23f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherView.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * The container for the user switcher on Keyguard.
- */
-public class KeyguardUserSwitcherView extends FrameLayout {
-
-    public KeyguardUserSwitcherView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt
index 5c1a427..4d33ed1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt
@@ -16,15 +16,14 @@
 
 import android.bluetooth.BluetoothAdapter
 import android.bluetooth.BluetoothProfile
+import com.android.app.tracing.coroutines.launchTraced as launch
 import com.android.settingslib.bluetooth.CachedBluetoothDevice
 import com.android.settingslib.bluetooth.LocalBluetoothManager
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
-import com.android.app.tracing.coroutines.launchTraced as launch
 import kotlinx.coroutines.withContext
 
 /**
@@ -52,7 +51,7 @@
 class BluetoothRepositoryImpl
 @Inject
 constructor(
-    @Application private val scope: CoroutineScope,
+    @Background private val scope: CoroutineScope,
     @Background private val bgDispatcher: CoroutineDispatcher,
     private val localBluetoothManager: LocalBluetoothManager?,
 ) : BluetoothRepository {
@@ -67,7 +66,7 @@
     }
 
     private suspend fun fetchConnectionStatus(
-        currentDevices: Collection<CachedBluetoothDevice>,
+        currentDevices: Collection<CachedBluetoothDevice>
     ): ConnectionStatusModel {
         return withContext(bgDispatcher) {
             val minimumMaxConnectionState =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
index 2a0812b..73cdf48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/data/repository/UserSetupRepository.kt
@@ -16,11 +16,10 @@
 
 package com.android.systemui.statusbar.policy.data.repository
 
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -49,7 +48,7 @@
 constructor(
     private val deviceProvisionedController: DeviceProvisionedController,
     @Background private val bgDispatcher: CoroutineDispatcher,
-    @Application scope: CoroutineScope,
+    @Background scope: CoroutineScope,
 ) : UserSetupRepository {
     override val isUserSetUp: StateFlow<Boolean> =
         conflatedCallbackFlow {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
index a1d5cbe..9ff0d18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
@@ -44,6 +44,7 @@
 import com.android.systemui.dialog.ui.composable.AlertDialogContent
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.ComponentSystemUIDialog
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -67,6 +68,7 @@
     private val viewModel: Provider<ModesDialogViewModel>,
     private val dialogEventLogger: ModesDialogEventLogger,
     @Main private val mainCoroutineContext: CoroutineContext,
+    private val shadeDisplayContextRepository: ShadeDialogContextInteractor,
 ) : SystemUIDialog.Delegate {
     // NOTE: This should only be accessed/written from the main thread.
     @VisibleForTesting var currentDialog: ComponentSystemUIDialog? = null
@@ -78,7 +80,10 @@
             currentDialog?.dismiss()
         }
 
-        currentDialog = sysuiDialogFactory.create { ModesDialogContent(it) }
+        currentDialog =
+            sysuiDialogFactory.create(context = shadeDisplayContextRepository.context) {
+                ModesDialogContent(it)
+            }
         currentDialog
             ?.lifecycle
             ?.addObserver(
@@ -106,9 +111,8 @@
                 modifier =
                     Modifier.semantics {
                         testTagsAsResourceId = true
-                        paneTitle = dialog.context.getString(
-                            R.string.accessibility_desc_quick_settings
-                        )
+                        paneTitle =
+                            dialog.context.getString(R.string.accessibility_desc_quick_settings)
                     },
                 title = {
                     Text(
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
index 3fa3f63..fbf7072 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/TouchpadTutorialModule.kt
@@ -27,7 +27,11 @@
 import com.android.systemui.touchpad.tutorial.domain.interactor.TouchpadGesturesInteractor
 import com.android.systemui.touchpad.tutorial.ui.composable.BackGestureTutorialScreen
 import com.android.systemui.touchpad.tutorial.ui.composable.HomeGestureTutorialScreen
+import com.android.systemui.touchpad.tutorial.ui.gesture.VelocityTracker
+import com.android.systemui.touchpad.tutorial.ui.gesture.VerticalVelocityTracker
 import com.android.systemui.touchpad.tutorial.ui.view.TouchpadTutorialActivity
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.BackGestureScreenViewModel
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureScreenViewModel
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
@@ -45,8 +49,11 @@
 
     companion object {
         @Provides
-        fun touchpadScreensProvider(): TouchpadTutorialScreensProvider {
-            return ScreensProvider
+        fun touchpadScreensProvider(
+            backGestureScreenViewModel: BackGestureScreenViewModel,
+            homeGestureScreenViewModel: HomeGestureScreenViewModel,
+        ): TouchpadTutorialScreensProvider {
+            return ScreensProvider(backGestureScreenViewModel, homeGestureScreenViewModel)
         }
 
         @SysUISingleton
@@ -59,17 +66,22 @@
         ): TouchpadGesturesInteractor {
             return TouchpadGesturesInteractor(sysUiState, displayTracker, backgroundScope, logger)
         }
+
+        @Provides fun velocityTracker(): VelocityTracker = VerticalVelocityTracker()
     }
 }
 
-private object ScreensProvider : TouchpadTutorialScreensProvider {
+private class ScreensProvider(
+    val backGestureScreenViewModel: BackGestureScreenViewModel,
+    val homeGestureScreenViewModel: HomeGestureScreenViewModel,
+) : TouchpadTutorialScreensProvider {
     @Composable
     override fun BackGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
-        BackGestureTutorialScreen(onDoneButtonClicked, onBack)
+        BackGestureTutorialScreen(backGestureScreenViewModel, onDoneButtonClicked, onBack)
     }
 
     @Composable
     override fun HomeGesture(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
-        HomeGestureTutorialScreen(onDoneButtonClicked, onBack)
+        HomeGestureTutorialScreen(homeGestureScreenViewModel, onDoneButtonClicked, onBack)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
index e1cc11a..804a764 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
@@ -16,26 +16,22 @@
 
 package com.android.systemui.touchpad.tutorial.ui.composable
 
-import android.content.res.Resources
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
 import com.airbnb.lottie.compose.rememberLottieDynamicProperties
 import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
 import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
 import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureRecognizer
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
-import com.android.systemui.util.kotlin.pairwiseBy
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.BackGestureScreenViewModel
 
 @Composable
-fun BackGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
+fun BackGestureTutorialScreen(
+    viewModel: BackGestureScreenViewModel,
+    onDoneButtonClicked: () -> Unit,
+    onBack: () -> Unit,
+) {
     val screenConfig =
         TutorialScreenConfig(
             colors = rememberScreenColors(),
@@ -50,40 +46,15 @@
                 ),
             animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_back_edu),
         )
-    val recognizer = rememberBackGestureRecognizer(LocalContext.current.resources)
-    val gestureUiState: Flow<GestureUiState> =
-        remember(recognizer) {
-            GestureFlowAdapter(recognizer).gestureStateAsFlow.pairwiseBy(GestureState.NotStarted) {
-                previous,
-                current ->
-                val (startMarker, endMarker) = getMarkers(current)
-                current.toGestureUiState(
-                    progressStartMarker = startMarker,
-                    progressEndMarker = endMarker,
-                    successAnimation = successAnimation(previous),
-                )
-            }
-        }
-    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
-}
-
-@Composable
-private fun rememberBackGestureRecognizer(resources: Resources): GestureRecognizer {
-    val distance =
-        resources.getDimensionPixelSize(R.dimen.touchpad_tutorial_gestures_distance_threshold)
-    return remember(distance) { BackGestureRecognizer(distance) }
-}
-
-private fun getMarkers(it: GestureState): Pair<String, String> {
-    return if (it is GestureState.InProgress && it.direction == GestureDirection.LEFT) {
-        "gesture to L" to "end progress L"
-    } else "gesture to R" to "end progress R"
-}
-
-private fun successAnimation(previous: GestureState): Int {
-    return if (previous is GestureState.InProgress && previous.direction == GestureDirection.LEFT) {
-        R.raw.trackpad_back_success_left
-    } else R.raw.trackpad_back_success_right
+    GestureTutorialScreen(
+        screenConfig = screenConfig,
+        gestureUiStateFlow = viewModel.gestureUiState,
+        motionEventConsumer = viewModel::handleEvent,
+        easterEggTriggeredFlow = viewModel.easterEggTriggered,
+        onEasterEggFinished = viewModel::onEasterEggFinished,
+        onDoneButtonClicked = onDoneButtonClicked,
+        onBack = onBack,
+    )
 }
 
 @Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
index ed84f9c..73c54af 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.touchpad.tutorial.ui.composable
 
+import android.view.MotionEvent
 import androidx.activity.compose.BackHandler
 import androidx.annotation.RawRes
 import androidx.compose.animation.core.Animatable
@@ -38,10 +39,7 @@
 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
 import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
 import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.NotStarted
-import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
 import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
-import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
 import kotlinx.coroutines.flow.Flow
 
 sealed interface GestureUiState {
@@ -99,22 +97,21 @@
 @Composable
 fun GestureTutorialScreen(
     screenConfig: TutorialScreenConfig,
-    gestureRecognizer: GestureRecognizer,
     gestureUiStateFlow: Flow<GestureUiState>,
+    motionEventConsumer: (MotionEvent) -> Boolean,
+    easterEggTriggeredFlow: Flow<Boolean>,
+    onEasterEggFinished: () -> Unit,
     onDoneButtonClicked: () -> Unit,
     onBack: () -> Unit,
 ) {
     BackHandler(onBack = onBack)
-    var easterEggTriggered by remember { mutableStateOf(false) }
+    val easterEggTriggered by easterEggTriggeredFlow.collectAsStateWithLifecycle(false)
     val gestureState by gestureUiStateFlow.collectAsStateWithLifecycle(NotStarted)
-    val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered = true }
-    val gestureHandler =
-        remember(gestureRecognizer) { TouchpadGestureHandler(gestureRecognizer, easterEggMonitor) }
     TouchpadGesturesHandlingBox(
-        gestureHandler,
+        motionEventConsumer,
         gestureState,
         easterEggTriggered,
-        resetEasterEggFlag = { easterEggTriggered = false },
+        onEasterEggFinished,
     ) {
         var lastState: TutorialActionState by remember {
             mutableStateOf(TutorialActionState.NotStarted)
@@ -126,10 +123,10 @@
 
 @Composable
 private fun TouchpadGesturesHandlingBox(
-    gestureHandler: TouchpadGestureHandler,
+    motionEventConsumer: (MotionEvent) -> Boolean,
     gestureState: GestureUiState,
     easterEggTriggered: Boolean,
-    resetEasterEggFlag: () -> Unit,
+    onEasterEggFinished: () -> Unit,
     modifier: Modifier = Modifier,
     content: @Composable BoxScope.() -> Unit,
 ) {
@@ -141,7 +138,7 @@
                 targetValue = 360f,
                 animationSpec = tween(durationMillis = 2000),
             )
-            resetEasterEggFlag()
+            onEasterEggFinished()
         }
     }
     Box(
@@ -156,7 +153,7 @@
                         if (gestureState is Finished) {
                             false
                         } else {
-                            gestureHandler.onMotionEvent(event)
+                            motionEventConsumer(event)
                         }
                     }
                 )
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
index 26604ca..5dcd788 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
@@ -16,23 +16,21 @@
 
 package com.android.systemui.touchpad.tutorial.ui.composable
 
-import android.content.res.Resources
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
 import com.airbnb.lottie.compose.rememberLottieDynamicProperties
 import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
 import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
 import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
-import com.android.systemui.touchpad.tutorial.ui.gesture.HomeGestureRecognizer
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureScreenViewModel
 
 @Composable
-fun HomeGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
+fun HomeGestureTutorialScreen(
+    viewModel: HomeGestureScreenViewModel,
+    onDoneButtonClicked: () -> Unit,
+    onBack: () -> Unit,
+) {
     val screenConfig =
         TutorialScreenConfig(
             colors = rememberScreenColors(),
@@ -47,26 +45,15 @@
                 ),
             animations = TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_home_edu),
         )
-    val recognizer = rememberHomeGestureRecognizer(LocalContext.current.resources)
-    val gestureUiState: Flow<GestureUiState> =
-        remember(recognizer) {
-            GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
-                it.toGestureUiState(
-                    progressStartMarker = "drag with gesture",
-                    progressEndMarker = "release playback realtime",
-                    successAnimation = R.raw.trackpad_home_success,
-                )
-            }
-        }
-    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
-}
-
-@Composable
-private fun rememberHomeGestureRecognizer(resources: Resources): GestureRecognizer {
-    val distance =
-        resources.getDimensionPixelSize(R.dimen.touchpad_tutorial_gestures_distance_threshold)
-    val velocity = resources.getDimension(R.dimen.touchpad_home_gesture_velocity_threshold)
-    return remember(distance) { HomeGestureRecognizer(distance, velocity) }
+    GestureTutorialScreen(
+        screenConfig = screenConfig,
+        gestureUiStateFlow = viewModel.gestureUiState,
+        motionEventConsumer = viewModel::handleEvent,
+        easterEggTriggeredFlow = viewModel.easterEggTriggered,
+        onEasterEggFinished = viewModel::onEasterEggFinished,
+        onDoneButtonClicked = onDoneButtonClicked,
+        onBack = onBack,
+    )
 }
 
 @Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
index 6400aca..7ff8389 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
@@ -16,23 +16,21 @@
 
 package com.android.systemui.touchpad.tutorial.ui.composable
 
-import android.content.res.Resources
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
 import com.airbnb.lottie.compose.rememberLottieDynamicProperties
 import com.android.compose.theme.LocalAndroidColorScheme
 import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
 import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
 import com.android.systemui.res.R
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
-import com.android.systemui.touchpad.tutorial.ui.gesture.RecentAppsGestureRecognizer
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureScreenViewModel
 
 @Composable
-fun RecentAppsGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
+fun RecentAppsGestureTutorialScreen(
+    viewModel: RecentAppsGestureScreenViewModel,
+    onDoneButtonClicked: () -> Unit,
+    onBack: () -> Unit,
+) {
     val screenConfig =
         TutorialScreenConfig(
             colors = rememberScreenColors(),
@@ -48,26 +46,15 @@
             animations =
                 TutorialScreenConfig.Animations(educationResId = R.raw.trackpad_recent_apps_edu),
         )
-    val recognizer = rememberRecentAppsGestureRecognizer(LocalContext.current.resources)
-    val gestureUiState: Flow<GestureUiState> =
-        remember(recognizer) {
-            GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
-                it.toGestureUiState(
-                    progressStartMarker = "drag with gesture",
-                    progressEndMarker = "onPause",
-                    successAnimation = R.raw.trackpad_recent_apps_success,
-                )
-            }
-        }
-    GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
-}
-
-@Composable
-private fun rememberRecentAppsGestureRecognizer(resources: Resources): GestureRecognizer {
-    val distance =
-        resources.getDimensionPixelSize(R.dimen.touchpad_tutorial_gestures_distance_threshold)
-    val velocity = resources.getDimension(R.dimen.touchpad_recent_apps_gesture_velocity_threshold)
-    return remember(distance, velocity) { RecentAppsGestureRecognizer(distance, velocity) }
+    GestureTutorialScreen(
+        screenConfig = screenConfig,
+        gestureUiStateFlow = viewModel.gestureUiState,
+        motionEventConsumer = viewModel::handleEvent,
+        easterEggTriggeredFlow = viewModel.easterEggTriggered,
+        onEasterEggFinished = viewModel::onEasterEggFinished,
+        onDoneButtonClicked = onDoneButtonClicked,
+        onBack = onBack,
+    )
 }
 
 @Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
index 6662fc5..6b4cbab 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/view/TouchpadTutorialActivity.kt
@@ -38,6 +38,9 @@
 import com.android.systemui.touchpad.tutorial.ui.composable.HomeGestureTutorialScreen
 import com.android.systemui.touchpad.tutorial.ui.composable.RecentAppsGestureTutorialScreen
 import com.android.systemui.touchpad.tutorial.ui.composable.TutorialSelectionScreen
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.BackGestureScreenViewModel
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.HomeGestureScreenViewModel
+import com.android.systemui.touchpad.tutorial.ui.viewmodel.RecentAppsGestureScreenViewModel
 import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.BACK_GESTURE
 import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.HOME_GESTURE
 import com.android.systemui.touchpad.tutorial.ui.viewmodel.Screen.RECENT_APPS_GESTURE
@@ -51,16 +54,28 @@
     private val viewModelFactory: TouchpadTutorialViewModel.Factory,
     private val logger: InputDeviceTutorialLogger,
     private val metricsLogger: KeyboardTouchpadTutorialMetricsLogger,
+    private val backGestureViewModel: BackGestureScreenViewModel,
+    private val homeGestureViewModel: HomeGestureScreenViewModel,
+    private val recentAppsGestureViewModel: RecentAppsGestureScreenViewModel,
 ) : ComponentActivity() {
 
-    private val vm by viewModels<TouchpadTutorialViewModel>(factoryProducer = { viewModelFactory })
+    private val tutorialViewModel by
+        viewModels<TouchpadTutorialViewModel>(factoryProducer = { viewModelFactory })
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         enableEdgeToEdge()
         setTitle(getString(R.string.launch_touchpad_tutorial_notification_content))
         setContent {
-            PlatformTheme { TouchpadTutorialScreen(vm, closeTutorial = ::finishTutorial) }
+            PlatformTheme {
+                TouchpadTutorialScreen(
+                    tutorialViewModel,
+                    backGestureViewModel,
+                    homeGestureViewModel,
+                    recentAppsGestureViewModel,
+                    closeTutorial = ::finishTutorial,
+                )
+            }
         }
         // required to handle 3+ fingers on touchpad
         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
@@ -75,17 +90,23 @@
 
     override fun onResume() {
         super.onResume()
-        vm.onOpened()
+        tutorialViewModel.onOpened()
     }
 
     override fun onPause() {
         super.onPause()
-        vm.onClosed()
+        tutorialViewModel.onClosed()
     }
 }
 
 @Composable
-fun TouchpadTutorialScreen(vm: TouchpadTutorialViewModel, closeTutorial: () -> Unit) {
+fun TouchpadTutorialScreen(
+    vm: TouchpadTutorialViewModel,
+    backGestureViewModel: BackGestureScreenViewModel,
+    homeGestureViewModel: HomeGestureScreenViewModel,
+    recentAppsGestureViewModel: RecentAppsGestureScreenViewModel,
+    closeTutorial: () -> Unit,
+) {
     val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED)
     var lastSelectedScreen by remember { mutableStateOf(TUTORIAL_SELECTION) }
     when (activeScreen) {
@@ -108,16 +129,19 @@
             )
         BACK_GESTURE ->
             BackGestureTutorialScreen(
+                backGestureViewModel,
                 onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) },
                 onBack = { vm.goTo(TUTORIAL_SELECTION) },
             )
         HOME_GESTURE ->
             HomeGestureTutorialScreen(
+                homeGestureViewModel,
                 onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) },
                 onBack = { vm.goTo(TUTORIAL_SELECTION) },
             )
         RECENT_APPS_GESTURE ->
             RecentAppsGestureTutorialScreen(
+                recentAppsGestureViewModel,
                 onDoneButtonClicked = { vm.goTo(TUTORIAL_SELECTION) },
                 onBack = { vm.goTo(TUTORIAL_SELECTION) },
             )
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt
new file mode 100644
index 0000000..0154c91
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/BackGestureScreenViewModel.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.view.MotionEvent
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
+import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureRecognizer
+import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureDirection
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
+import com.android.systemui.util.kotlin.pairwiseBy
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+
+class BackGestureScreenViewModel
+@Inject
+constructor(configurationInteractor: ConfigurationInteractor) : TouchpadTutorialScreenViewModel {
+
+    private val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered.value = true }
+    override val easterEggTriggered = MutableStateFlow(false)
+
+    private var handler: TouchpadGestureHandler? = null
+
+    private val distanceThreshold: Flow<Int> =
+        configurationInteractor
+            .dimensionPixelSize(R.dimen.touchpad_tutorial_gestures_distance_threshold)
+            .distinctUntilChanged()
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    override val gestureUiState: Flow<GestureUiState> =
+        distanceThreshold
+            .flatMapLatest {
+                val recognizer = BackGestureRecognizer(gestureDistanceThresholdPx = it)
+                handler = TouchpadGestureHandler(recognizer, easterEggMonitor)
+                GestureFlowAdapter(recognizer).gestureStateAsFlow
+            }
+            .pairwiseBy(GestureState.NotStarted) { previous, current ->
+                toGestureUiState(current, previous)
+            }
+
+    override fun handleEvent(event: MotionEvent): Boolean {
+        return handler?.onMotionEvent(event) ?: false
+    }
+
+    private fun toGestureUiState(current: GestureState, previous: GestureState): GestureUiState {
+        val (startMarker, endMarker) =
+            if (current is InProgress && current.direction == GestureDirection.LEFT) {
+                "gesture to L" to "end progress L"
+            } else "gesture to R" to "end progress R"
+        return current.toGestureUiState(
+            progressStartMarker = startMarker,
+            progressEndMarker = endMarker,
+            successAnimation = successAnimation(previous),
+        )
+    }
+
+    private fun successAnimation(previous: GestureState): Int {
+        return if (previous is InProgress && previous.direction == GestureDirection.LEFT) {
+            R.raw.trackpad_back_success_left
+        } else R.raw.trackpad_back_success_right
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt
new file mode 100644
index 0000000..1c865f5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/HomeGestureScreenViewModel.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.content.res.Resources
+import android.view.MotionEvent
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
+import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.android.systemui.touchpad.tutorial.ui.gesture.HomeGestureRecognizer
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
+import com.android.systemui.touchpad.tutorial.ui.gesture.VelocityTracker
+import com.android.systemui.touchpad.tutorial.ui.gesture.VerticalVelocityTracker
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+
+class HomeGestureScreenViewModel
+@Inject
+constructor(
+    val configurationInteractor: ConfigurationInteractor,
+    @Main val resources: Resources,
+    val velocityTracker: VelocityTracker = VerticalVelocityTracker(),
+) : TouchpadTutorialScreenViewModel {
+
+    private val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered.value = true }
+    override val easterEggTriggered = MutableStateFlow(false)
+
+    private var handler: TouchpadGestureHandler? = null
+
+    private val distanceThreshold: Flow<Int> =
+        configurationInteractor
+            .dimensionPixelSize(R.dimen.touchpad_tutorial_gestures_distance_threshold)
+            .distinctUntilChanged()
+
+    private val velocityThreshold: Flow<Float> =
+        configurationInteractor.onAnyConfigurationChange
+            .map { resources.getDimension(R.dimen.touchpad_home_gesture_velocity_threshold) }
+            .distinctUntilChanged()
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    override val gestureUiState: Flow<GestureUiState> =
+        distanceThreshold
+            .combine(velocityThreshold, { distance, velocity -> distance to velocity })
+            .flatMapLatest { (distance, velocity) ->
+                val recognizer =
+                    HomeGestureRecognizer(
+                        gestureDistanceThresholdPx = distance,
+                        velocityThresholdPxPerMs = velocity,
+                        velocityTracker = velocityTracker,
+                    )
+                handler = TouchpadGestureHandler(recognizer, easterEggMonitor)
+                GestureFlowAdapter(recognizer).gestureStateAsFlow
+            }
+            .map { toGestureUiState(it) }
+
+    private fun toGestureUiState(it: GestureState) =
+        it.toGestureUiState(
+            progressStartMarker = "drag with gesture",
+            progressEndMarker = "release playback realtime",
+            successAnimation = R.raw.trackpad_home_success,
+        )
+
+    override fun handleEvent(event: MotionEvent): Boolean {
+        return handler?.onMotionEvent(event) ?: false
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt
new file mode 100644
index 0000000..09947a8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/RecentAppsGestureScreenViewModel.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.content.res.Resources
+import android.view.MotionEvent
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import com.android.systemui.touchpad.tutorial.ui.composable.toGestureUiState
+import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
+import com.android.systemui.touchpad.tutorial.ui.gesture.RecentAppsGestureRecognizer
+import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
+import com.android.systemui.touchpad.tutorial.ui.gesture.VelocityTracker
+import com.android.systemui.touchpad.tutorial.ui.gesture.VerticalVelocityTracker
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+
+class RecentAppsGestureScreenViewModel
+@Inject
+constructor(
+    configurationInteractor: ConfigurationInteractor,
+    @Main private val resources: Resources,
+    private val velocityTracker: VelocityTracker = VerticalVelocityTracker(),
+) : TouchpadTutorialScreenViewModel {
+
+    private val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered.value = true }
+    override val easterEggTriggered = MutableStateFlow(false)
+
+    private var handler: TouchpadGestureHandler? = null
+
+    private val distanceThreshold: Flow<Int> =
+        configurationInteractor.onAnyConfigurationChange
+            .map {
+                resources.getDimensionPixelSize(
+                    R.dimen.touchpad_tutorial_gestures_distance_threshold
+                )
+            }
+            .distinctUntilChanged()
+
+    private val velocityThreshold: Flow<Float> =
+        configurationInteractor.onAnyConfigurationChange
+            .map { resources.getDimension(R.dimen.touchpad_recent_apps_gesture_velocity_threshold) }
+            .distinctUntilChanged()
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    override val gestureUiState: Flow<GestureUiState> =
+        distanceThreshold
+            .combine(velocityThreshold, { distance, velocity -> distance to velocity })
+            .flatMapLatest { (distance, velocity) ->
+                val recognizer =
+                    RecentAppsGestureRecognizer(
+                        gestureDistanceThresholdPx = distance,
+                        velocityThresholdPxPerMs = velocity,
+                        velocityTracker = velocityTracker,
+                    )
+                handler = TouchpadGestureHandler(recognizer, easterEggMonitor)
+                GestureFlowAdapter(recognizer).gestureStateAsFlow
+            }
+            .map { toGestureUiState(it) }
+
+    private fun toGestureUiState(it: GestureState) =
+        it.toGestureUiState(
+            progressStartMarker = "drag with gesture",
+            progressEndMarker = "onPause",
+            successAnimation = R.raw.trackpad_recent_apps_success,
+        )
+
+    override fun handleEvent(event: MotionEvent): Boolean {
+        return handler?.onMotionEvent(event) ?: false
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt
new file mode 100644
index 0000000..500f6a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/viewmodel/TouchpadTutorialScreenViewModel.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.touchpad.tutorial.ui.viewmodel
+
+import android.view.MotionEvent
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+interface TouchpadTutorialScreenViewModel {
+    val gestureUiState: Flow<GestureUiState>
+    val easterEggTriggered: MutableStateFlow<Boolean>
+
+    fun onEasterEggFinished() {
+        easterEggTriggered.value = false
+    }
+
+    fun handleEvent(event: MotionEvent): Boolean
+}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
index a382cf9..e08114f 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
@@ -21,10 +21,8 @@
 import android.hardware.devicestate.DeviceStateManager
 import android.os.PowerManager
 import android.provider.Settings
-import androidx.core.view.OneShotPreDrawListener
 import com.android.internal.util.LatencyTracker
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.ToAodFoldTransitionInteractor
@@ -125,11 +123,7 @@
 
     private val shadeFoldAnimator: ShadeFoldAnimator
         get() {
-            return if (MigrateClocksToBlueprint.isEnabled) {
-                foldTransitionInteractor.get().foldAnimator
-            } else {
-                shadeViewController.shadeFoldAnimator
-            }
+            return foldTransitionInteractor.get().foldAnimator
         }
 
     private fun setAnimationState(playing: Boolean) {
@@ -164,15 +158,7 @@
                 setAnimationState(playing = true)
                 shadeFoldAnimator.prepareFoldToAodAnimation()
 
-                // We don't need to wait for the scrim as it is already displayed
-                // but we should wait for the initial animation preparations to be drawn
-                // (setting initial alpha/translation)
-                // TODO(b/254878364): remove this call to NPVC.getView()
-                if (!MigrateClocksToBlueprint.isEnabled) {
-                    shadeFoldAnimator.view?.let { OneShotPreDrawListener.add(it, onReady) }
-                } else {
-                    onReady.run()
-                }
+                onReady.run()
             } else {
                 // No animation, call ready callback immediately
                 onReady.run()
@@ -252,7 +238,7 @@
                 if (isFolded) {
                     foldToAodLatencyTracker.onFolded()
                 }
-            }
+            },
         )
 
     /**
@@ -272,6 +258,7 @@
                 latencyTracker.onActionStart(LatencyTracker.ACTION_FOLD_TO_AOD)
             }
         }
+
         /**
          * Called once the Fold -> AOD animation is started.
          *
diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
index 102fcc0..e4b2dc2 100644
--- a/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitcherDialogCoordinator.kt
@@ -18,7 +18,6 @@
 package com.android.systemui.user.ui.dialog
 
 import android.app.Dialog
-import android.content.Context
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.logging.UiEventLogger
 import com.android.settingslib.users.UserCreatingDialog
@@ -32,6 +31,7 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.tiles.UserDetailView
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
 import com.android.systemui.user.UserSwitchFullscreenDialog
 import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
 import com.android.systemui.user.domain.model.ShowDialogRequestModel
@@ -48,7 +48,6 @@
 class UserSwitcherDialogCoordinator
 @Inject
 constructor(
-    @Application private val context: Lazy<Context>,
     @Application private val applicationScope: Lazy<CoroutineScope>,
     private val falsingManager: Lazy<FalsingManager>,
     private val broadcastSender: Lazy<BroadcastSender>,
@@ -59,6 +58,7 @@
     private val activityStarter: Lazy<ActivityStarter>,
     private val falsingCollector: Lazy<FalsingCollector>,
     private val userSwitcherViewModel: Lazy<UserSwitcherViewModel>,
+    private val shadeDialogContextInteractor: Lazy<ShadeDialogContextInteractor>,
 ) : CoreStartable {
 
     private var currentDialog: Dialog? = null
@@ -71,12 +71,13 @@
     private fun startHandlingDialogShowRequests() {
         applicationScope.get().launch {
             interactor.get().dialogShowRequests.filterNotNull().collect { request ->
+                val context = shadeDialogContextInteractor.get().context
                 val (dialog, dialogCuj) =
                     when (request) {
                         is ShowDialogRequestModel.ShowAddUserDialog ->
                             Pair(
                                 AddUserDialog(
-                                    context = context.get(),
+                                    context = context,
                                     userHandle = request.userHandle,
                                     isKeyguardShowing = request.isKeyguardShowing,
                                     showEphemeralMessage = request.showEphemeralMessage,
@@ -92,7 +93,7 @@
                         is ShowDialogRequestModel.ShowUserCreationDialog ->
                             Pair(
                                 UserCreatingDialog(
-                                    context.get(),
+                                    context,
                                     request.isGuest,
                                 ),
                                 null,
@@ -100,7 +101,7 @@
                         is ShowDialogRequestModel.ShowExitGuestDialog ->
                             Pair(
                                 ExitGuestDialog(
-                                    context = context.get(),
+                                    context = context,
                                     guestUserId = request.guestUserId,
                                     isGuestEphemeral = request.isGuestEphemeral,
                                     targetUserId = request.targetUserId,
@@ -117,7 +118,7 @@
                         is ShowDialogRequestModel.ShowUserSwitcherDialog ->
                             Pair(
                                 UserSwitchDialog(
-                                    context = context.get(),
+                                    context = context,
                                     adapter = userDetailAdapterProvider.get(),
                                     uiEventLogger = eventLogger.get(),
                                     falsingManager = falsingManager.get(),
@@ -132,7 +133,7 @@
                         is ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog ->
                             Pair(
                                 UserSwitchFullscreenDialog(
-                                    context = context.get(),
+                                    context = context,
                                     falsingCollector = falsingCollector.get(),
                                     userSwitcherViewModel = userSwitcherViewModel.get(),
                                 ),
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
index f04fb2c..8bb0279 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt
@@ -24,16 +24,15 @@
 import androidx.annotation.LayoutRes
 import androidx.compose.ui.util.fastForEachIndexed
 import androidx.constraintlayout.motion.widget.MotionLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.dynamicanimation.animation.DynamicAnimation
 import androidx.dynamicanimation.animation.FloatValueHolder
 import androidx.dynamicanimation.animation.SpringAnimation
 import androidx.dynamicanimation.animation.SpringForce
 import com.android.internal.R as internalR
 import com.android.systemui.res.R
-import com.android.systemui.util.children
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
 import com.android.systemui.volume.dialog.ringer.ui.util.VolumeDialogRingerDrawerTransitionListener
+import com.android.systemui.volume.dialog.ringer.ui.util.updateCloseState
+import com.android.systemui.volume.dialog.ringer.ui.util.updateOpenState
 import com.android.systemui.volume.dialog.ringer.ui.viewmodel.RingerButtonUiModel
 import com.android.systemui.volume.dialog.ringer.ui.viewmodel.RingerButtonViewModel
 import com.android.systemui.volume.dialog.ringer.ui.viewmodel.RingerDrawerState
@@ -44,13 +43,16 @@
 import javax.inject.Inject
 import kotlin.properties.Delegates
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.mapLatest
 import kotlinx.coroutines.launch
 
 private const val CLOSE_DRAWER_DELAY = 300L
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @VolumeDialogScope
 class VolumeDialogRingerViewBinder
 @Inject
@@ -93,8 +95,9 @@
         }
         drawerContainer.setTransitionListener(ringerDrawerTransitionListener)
         volumeDialogBackgroundView.background = volumeDialogBackgroundView.background.mutate()
+
         viewModel.ringerViewModel
-            .onEach { ringerState ->
+            .mapLatest { ringerState ->
                 when (ringerState) {
                     is RingerViewModelState.Available -> {
                         val uiModel = ringerState.uiModel
@@ -110,7 +113,10 @@
                                     unselectedButtonUiModel,
                                 )
                                 ringerDrawerTransitionListener.setProgressChangeEnabled(true)
-                                drawerContainer.closeDrawer(uiModel.currentButtonIndex)
+                                drawerContainer.closeDrawer(
+                                    uiModel.currentButtonIndex,
+                                    ringerState.orientation,
+                                )
                             }
 
                             is RingerDrawerState.Closed -> {
@@ -125,8 +131,10 @@
                                         unselectedButtonUiModel,
                                         onProgressChanged = { progress, isReverse ->
                                             // Let's make button progress when switching matches
-                                            // motionLayout transition progress. When full radius,
-                                            // progress is 0.0. When small radius, progress is 1.0.
+                                            // motionLayout transition progress. When full
+                                            // radius,
+                                            // progress is 0.0. When small radius, progress is
+                                            // 1.0.
                                             backgroundAnimationProgress =
                                                 if (isReverse) {
                                                     1F - progress
@@ -147,7 +155,10 @@
                                                 true
                                             )
                                         }
-                                        drawerContainer.closeDrawer(uiModel.currentButtonIndex)
+                                        drawerContainer.closeDrawer(
+                                            uiModel.currentButtonIndex,
+                                            ringerState.orientation,
+                                        )
                                     }
                                 }
                             }
@@ -167,6 +178,7 @@
                                 } else {
                                     ringerDrawerTransitionListener.setProgressChangeEnabled(true)
                                 }
+                                updateOpenState(drawerContainer, ringerState.orientation)
                                 drawerContainer.transitionToState(
                                     R.id.volume_dialog_ringer_drawer_open
                                 )
@@ -211,35 +223,38 @@
             val unselectedButton =
                 getChildAt(count - previousIndex - 1)
                     .requireViewById<ImageButton>(R.id.volume_drawer_button)
-
-            // On roundness animation end.
-            val roundnessAnimationEndListener =
-                DynamicAnimation.OnAnimationEndListener { _, _, _, _ ->
-                    postDelayed(
-                        { bindButtons(viewModel, uiModel, onAnimationEnd, isAnimated = true) },
-                        CLOSE_DRAWER_DELAY,
-                    )
-                }
             // We only need to execute on roundness animation end and volume dialog background
             // progress update once because these changes should be applied once on volume dialog
             // background and ringer drawer views.
-            selectedButton.animateTo(
-                selectedButtonUiModel,
-                if (uiModel.currentButtonIndex == count - 1) {
-                    onProgressChanged
-                } else {
-                    { _, _ -> }
-                },
-                roundnessAnimationEndListener,
-            )
-            unselectedButton.animateTo(
-                unselectedButtonUiModel,
-                if (previousIndex == count - 1) {
-                    onProgressChanged
-                } else {
-                    { _, _ -> }
-                },
-            )
+            val selectedCornerRadius = (selectedButton.background as GradientDrawable).cornerRadius
+            if (selectedCornerRadius.toInt() != selectedButtonUiModel.cornerRadius) {
+                selectedButton.animateTo(
+                    selectedButtonUiModel,
+                    if (uiModel.currentButtonIndex == count - 1) {
+                        onProgressChanged
+                    } else {
+                        { _, _ -> }
+                    },
+                )
+            }
+            val unselectedCornerRadius =
+                (unselectedButton.background as GradientDrawable).cornerRadius
+            if (unselectedCornerRadius.toInt() != unselectedButtonUiModel.cornerRadius) {
+                unselectedButton.animateTo(
+                    unselectedButtonUiModel,
+                    if (previousIndex == count - 1) {
+                        onProgressChanged
+                    } else {
+                        { _, _ -> }
+                    },
+                )
+            }
+            coroutineScope {
+                launch {
+                    delay(CLOSE_DRAWER_DELAY)
+                    bindButtons(viewModel, uiModel, onAnimationEnd, isAnimated = true)
+                }
+            }
         } else {
             bindButtons(viewModel, uiModel, onAnimationEnd)
         }
@@ -318,111 +333,19 @@
                     inflater.inflate(viewLayoutId, this, true)
                     getChildAt(childCount - 1).id = View.generateViewId()
                 }
-                cloneConstraintSet(R.id.volume_dialog_ringer_drawer_open)
-                    .adjustOpenConstraintsForDrawer(this)
             }
         }
     }
 
-    private fun MotionLayout.closeDrawer(selectedIndex: Int) {
+    private fun MotionLayout.closeDrawer(selectedIndex: Int, orientation: Int) {
         setTransition(R.id.close_to_open_transition)
-        cloneConstraintSet(R.id.volume_dialog_ringer_drawer_close)
-            .adjustClosedConstraintsForDrawer(selectedIndex, this)
+        updateCloseState(this, selectedIndex, orientation)
         transitionToState(R.id.volume_dialog_ringer_drawer_close)
     }
 
-    private fun ConstraintSet.adjustOpenConstraintsForDrawer(motionLayout: MotionLayout) {
-        motionLayout.children.forEachIndexed { index, button ->
-            setButtonPositionConstraints(motionLayout, index, button)
-            setAlpha(button.id, 1.0F)
-            constrainWidth(
-                button.id,
-                motionLayout.context.resources.getDimensionPixelSize(
-                    R.dimen.volume_dialog_ringer_drawer_button_size
-                ),
-            )
-            constrainHeight(
-                button.id,
-                motionLayout.context.resources.getDimensionPixelSize(
-                    R.dimen.volume_dialog_ringer_drawer_button_size
-                ),
-            )
-            if (index != motionLayout.childCount - 1) {
-                setMargin(
-                    button.id,
-                    ConstraintSet.BOTTOM,
-                    motionLayout.context.resources.getDimensionPixelSize(
-                        R.dimen.volume_dialog_components_spacing
-                    ),
-                )
-            }
-        }
-        motionLayout.updateState(R.id.volume_dialog_ringer_drawer_open, this)
-    }
-
-    private fun ConstraintSet.adjustClosedConstraintsForDrawer(
-        selectedIndex: Int,
-        motionLayout: MotionLayout,
-    ) {
-        motionLayout.children.forEachIndexed { index, button ->
-            setButtonPositionConstraints(motionLayout, index, button)
-            constrainWidth(
-                button.id,
-                motionLayout.context.resources.getDimensionPixelSize(
-                    R.dimen.volume_dialog_ringer_drawer_button_size
-                ),
-            )
-            if (selectedIndex != motionLayout.childCount - index - 1) {
-                setAlpha(button.id, 0.0F)
-                constrainHeight(button.id, 0)
-                setMargin(button.id, ConstraintSet.BOTTOM, 0)
-            } else {
-                setAlpha(button.id, 1.0F)
-                constrainHeight(
-                    button.id,
-                    motionLayout.context.resources.getDimensionPixelSize(
-                        R.dimen.volume_dialog_ringer_drawer_button_size
-                    ),
-                )
-            }
-        }
-        motionLayout.updateState(R.id.volume_dialog_ringer_drawer_close, this)
-    }
-
-    private fun ConstraintSet.setButtonPositionConstraints(
-        motionLayout: MotionLayout,
-        index: Int,
-        button: View,
-    ) {
-        if (motionLayout.getChildAt(index - 1) == null) {
-            connect(button.id, ConstraintSet.TOP, motionLayout.id, ConstraintSet.TOP)
-        } else {
-            connect(
-                button.id,
-                ConstraintSet.TOP,
-                motionLayout.getChildAt(index - 1).id,
-                ConstraintSet.BOTTOM,
-            )
-        }
-
-        if (motionLayout.getChildAt(index + 1) == null) {
-            connect(button.id, ConstraintSet.BOTTOM, motionLayout.id, ConstraintSet.BOTTOM)
-        } else {
-            connect(
-                button.id,
-                ConstraintSet.BOTTOM,
-                motionLayout.getChildAt(index + 1).id,
-                ConstraintSet.TOP,
-            )
-        }
-        connect(button.id, ConstraintSet.START, motionLayout.id, ConstraintSet.START)
-        connect(button.id, ConstraintSet.END, motionLayout.id, ConstraintSet.END)
-    }
-
     private suspend fun ImageButton.animateTo(
         ringerButtonUiModel: RingerButtonUiModel,
         onProgressChanged: (Float, Boolean) -> Unit = { _, _ -> },
-        roundnessAnimationEndListener: DynamicAnimation.OnAnimationEndListener? = null,
     ) {
         val roundnessAnimation =
             SpringAnimation(FloatValueHolder(0F)).setSpring(roundnessSpringForce)
@@ -430,37 +353,32 @@
         val radius = (background as GradientDrawable).cornerRadius
         val cornerRadiusDiff =
             ringerButtonUiModel.cornerRadius - (background as GradientDrawable).cornerRadius
-        val roundnessAnimationUpdateListener =
-            DynamicAnimation.OnAnimationUpdateListener { _, value, _ ->
+        coroutineScope {
+            launch {
+                colorAnimation.suspendAnimate { value ->
+                    val currentIconColor =
+                        rgbEvaluator.evaluate(
+                            value.coerceIn(0F, 1F),
+                            imageTintList?.colors?.first(),
+                            ringerButtonUiModel.tintColor,
+                        ) as Int
+                    val currentBgColor =
+                        rgbEvaluator.evaluate(
+                            value.coerceIn(0F, 1F),
+                            (background as GradientDrawable).color?.colors?.get(0),
+                            ringerButtonUiModel.backgroundColor,
+                        ) as Int
+
+                    (background as GradientDrawable).setColor(currentBgColor)
+                    background.invalidateSelf()
+                    setColorFilter(currentIconColor)
+                }
+            }
+            roundnessAnimation.suspendAnimate { value ->
                 onProgressChanged(value, cornerRadiusDiff > 0F)
                 (background as GradientDrawable).cornerRadius = radius + value * cornerRadiusDiff
                 background.invalidateSelf()
             }
-        val colorAnimationUpdateListener =
-            DynamicAnimation.OnAnimationUpdateListener { _, value, _ ->
-                val currentIconColor =
-                    rgbEvaluator.evaluate(
-                        value.coerceIn(0F, 1F),
-                        imageTintList?.colors?.first(),
-                        ringerButtonUiModel.tintColor,
-                    ) as Int
-                val currentBgColor =
-                    rgbEvaluator.evaluate(
-                        value.coerceIn(0F, 1F),
-                        (background as GradientDrawable).color?.colors?.get(0),
-                        ringerButtonUiModel.backgroundColor,
-                    ) as Int
-
-                (background as GradientDrawable).setColor(currentBgColor)
-                background.invalidateSelf()
-                setColorFilter(currentIconColor)
-            }
-        coroutineScope {
-            launch { colorAnimation.suspendAnimate(colorAnimationUpdateListener) }
-            roundnessAnimation.suspendAnimate(
-                roundnessAnimationUpdateListener,
-                roundnessAnimationEndListener,
-            )
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt
new file mode 100644
index 0000000..25ba1bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.dialog.ringer.ui.util
+
+import android.content.res.Configuration.ORIENTATION_LANDSCAPE
+import android.content.res.Configuration.ORIENTATION_PORTRAIT
+import android.view.View
+import androidx.constraintlayout.motion.widget.MotionLayout
+import androidx.constraintlayout.widget.ConstraintSet
+import com.android.systemui.res.R
+import com.android.systemui.util.children
+
+fun updateOpenState(ringerDrawer: MotionLayout, orientation: Int) {
+    val openSet = ringerDrawer.cloneConstraintSet(R.id.volume_dialog_ringer_drawer_open)
+    openSet.adjustOpenConstraintsForDrawer(ringerDrawer, orientation)
+    ringerDrawer.updateState(R.id.volume_dialog_ringer_drawer_open, openSet)
+}
+
+fun updateCloseState(ringerDrawer: MotionLayout, selectedIndex: Int, orientation: Int) {
+    val closeSet = ringerDrawer.cloneConstraintSet(R.id.volume_dialog_ringer_drawer_close)
+    closeSet.adjustClosedConstraintsForDrawer(ringerDrawer, selectedIndex, orientation)
+    ringerDrawer.updateState(R.id.volume_dialog_ringer_drawer_close, closeSet)
+}
+
+private fun ConstraintSet.setButtonPositionPortraitConstraints(
+    motionLayout: MotionLayout,
+    index: Int,
+    button: View,
+) {
+    if (motionLayout.getChildAt(index - 1) == null) {
+        connect(button.id, ConstraintSet.TOP, motionLayout.id, ConstraintSet.TOP)
+    } else {
+        connect(
+            button.id,
+            ConstraintSet.TOP,
+            motionLayout.getChildAt(index - 1).id,
+            ConstraintSet.BOTTOM,
+        )
+    }
+
+    if (motionLayout.getChildAt(index + 1) == null) {
+        connect(button.id, ConstraintSet.BOTTOM, motionLayout.id, ConstraintSet.BOTTOM)
+    } else {
+        connect(
+            button.id,
+            ConstraintSet.BOTTOM,
+            motionLayout.getChildAt(index + 1).id,
+            ConstraintSet.TOP,
+        )
+    }
+    connect(button.id, ConstraintSet.START, motionLayout.id, ConstraintSet.START)
+    connect(button.id, ConstraintSet.END, motionLayout.id, ConstraintSet.END)
+    clear(button.id, ConstraintSet.LEFT)
+    clear(button.id, ConstraintSet.RIGHT)
+}
+
+private fun ConstraintSet.setButtonPositionLandscapeConstraints(
+    motionLayout: MotionLayout,
+    index: Int,
+    button: View,
+) {
+    if (motionLayout.getChildAt(index - 1) == null) {
+        connect(button.id, ConstraintSet.LEFT, motionLayout.id, ConstraintSet.LEFT)
+    } else {
+        connect(
+            button.id,
+            ConstraintSet.LEFT,
+            motionLayout.getChildAt(index - 1).id,
+            ConstraintSet.RIGHT,
+        )
+    }
+    if (motionLayout.getChildAt(index + 1) == null) {
+        connect(button.id, ConstraintSet.RIGHT, motionLayout.id, ConstraintSet.RIGHT)
+    } else {
+        connect(
+            button.id,
+            ConstraintSet.RIGHT,
+            motionLayout.getChildAt(index + 1).id,
+            ConstraintSet.LEFT,
+        )
+    }
+    connect(button.id, ConstraintSet.TOP, motionLayout.id, ConstraintSet.TOP)
+    connect(button.id, ConstraintSet.BOTTOM, motionLayout.id, ConstraintSet.BOTTOM)
+    clear(button.id, ConstraintSet.START)
+    clear(button.id, ConstraintSet.END)
+}
+
+private fun ConstraintSet.adjustOpenConstraintsForDrawer(
+    motionLayout: MotionLayout,
+    lastOrientation: Int,
+) {
+    motionLayout.children.forEachIndexed { index, button ->
+        setAlpha(button.id, 1.0F)
+        constrainWidth(
+            button.id,
+            motionLayout.context.resources.getDimensionPixelSize(
+                R.dimen.volume_dialog_ringer_drawer_button_size
+            ),
+        )
+        constrainHeight(
+            button.id,
+            motionLayout.context.resources.getDimensionPixelSize(
+                R.dimen.volume_dialog_ringer_drawer_button_size
+            ),
+        )
+        when (lastOrientation) {
+            ORIENTATION_LANDSCAPE -> {
+                setButtonPositionLandscapeConstraints(motionLayout, index, button)
+                if (index != motionLayout.childCount - 1) {
+                    setMargin(
+                        button.id,
+                        ConstraintSet.RIGHT,
+                        motionLayout.context.resources.getDimensionPixelSize(
+                            R.dimen.volume_dialog_components_spacing
+                        ),
+                    )
+                } else {
+                    setMargin(button.id, ConstraintSet.RIGHT, 0)
+                }
+                setMargin(button.id, ConstraintSet.BOTTOM, 0)
+            }
+            ORIENTATION_PORTRAIT -> {
+                setButtonPositionPortraitConstraints(motionLayout, index, button)
+                if (index != motionLayout.childCount - 1) {
+                    setMargin(
+                        button.id,
+                        ConstraintSet.BOTTOM,
+                        motionLayout.context.resources.getDimensionPixelSize(
+                            R.dimen.volume_dialog_components_spacing
+                        ),
+                    )
+                } else {
+                    setMargin(button.id, ConstraintSet.BOTTOM, 0)
+                }
+                setMargin(button.id, ConstraintSet.RIGHT, 0)
+            }
+        }
+    }
+}
+
+private fun ConstraintSet.adjustClosedConstraintsForDrawer(
+    motionLayout: MotionLayout,
+    selectedIndex: Int,
+    lastOrientation: Int,
+) {
+    motionLayout.children.forEachIndexed { index, button ->
+        setMargin(button.id, ConstraintSet.RIGHT, 0)
+        setMargin(button.id, ConstraintSet.BOTTOM, 0)
+        when (lastOrientation) {
+            ORIENTATION_LANDSCAPE -> {
+                setButtonPositionLandscapeConstraints(motionLayout, index, button)
+                if (selectedIndex != motionLayout.childCount - index - 1) {
+                    setAlpha(button.id, 0.0F)
+                    constrainWidth(button.id, 0)
+                } else {
+                    setAlpha(button.id, 1.0F)
+                    constrainWidth(
+                        button.id,
+                        motionLayout.context.resources.getDimensionPixelSize(
+                            R.dimen.volume_dialog_ringer_drawer_button_size
+                        ),
+                    )
+                }
+                constrainHeight(
+                    button.id,
+                    motionLayout.context.resources.getDimensionPixelSize(
+                        R.dimen.volume_dialog_ringer_drawer_button_size
+                    ),
+                )
+            }
+            ORIENTATION_PORTRAIT -> {
+                setButtonPositionPortraitConstraints(motionLayout, index, button)
+                if (selectedIndex != motionLayout.childCount - index - 1) {
+                    setAlpha(button.id, 0.0F)
+                    constrainHeight(button.id, 0)
+                } else {
+                    setAlpha(button.id, 1.0F)
+                    constrainHeight(
+                        button.id,
+                        motionLayout.context.resources.getDimensionPixelSize(
+                            R.dimen.volume_dialog_ringer_drawer_button_size
+                        ),
+                    )
+                }
+                constrainWidth(
+                    button.id,
+                    motionLayout.context.resources.getDimensionPixelSize(
+                        R.dimen.volume_dialog_ringer_drawer_button_size
+                    ),
+                )
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModelState.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModelState.kt
index 78b00af..50898b6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModelState.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/RingerViewModelState.kt
@@ -19,7 +19,8 @@
 /** Models ringer view model state. */
 sealed class RingerViewModelState {
 
-    data class Available(val uiModel: RingerViewModel) : RingerViewModelState()
+    data class Available(val uiModel: RingerViewModel, val orientation: Int) :
+        RingerViewModelState()
 
     data object Unavailable : RingerViewModelState()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
index 627d75e..eec64d9 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModel.kt
@@ -33,6 +33,8 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.onConfigChanged
 import com.android.systemui.volume.Events
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
@@ -48,6 +50,7 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
@@ -65,19 +68,29 @@
     private val vibrator: VibratorHelper,
     private val volumeDialogLogger: VolumeDialogLogger,
     private val visibilityInteractor: VolumeDialogVisibilityInteractor,
+    configurationController: ConfigurationController,
 ) {
 
     private val drawerState = MutableStateFlow<RingerDrawerState>(RingerDrawerState.Initial)
+    private val orientation: StateFlow<Int> =
+        configurationController.onConfigChanged
+            .map { it.orientation }
+            .stateIn(
+                coroutineScope,
+                SharingStarted.Eagerly,
+                applicationContext.resources.configuration.orientation,
+            )
 
     val ringerViewModel: StateFlow<RingerViewModelState> =
         combine(
                 soundPolicyInteractor.isZenMuted(AudioStream(STREAM_RING)),
                 ringerInteractor.ringerModel,
                 drawerState,
-            ) { isZenMuted, ringerModel, state ->
+                orientation,
+            ) { isZenMuted, ringerModel, state, orientation ->
                 level = ringerModel.level
                 levelMax = ringerModel.levelMax
-                ringerModel.toViewModel(state, isZenMuted)
+                ringerModel.toViewModel(state, isZenMuted, orientation)
             }
             .flowOn(backgroundDispatcher)
             .stateIn(coroutineScope, SharingStarted.Eagerly, RingerViewModelState.Unavailable)
@@ -133,6 +146,7 @@
     private fun VolumeDialogRingerModel.toViewModel(
         drawerState: RingerDrawerState,
         isZenMuted: Boolean,
+        orientation: Int,
     ): RingerViewModelState {
         val currentIndex = availableModes.indexOf(currentRingerMode)
         if (currentIndex == -1) {
@@ -149,7 +163,8 @@
                         currentButtonIndex = currentIndex,
                         selectedButton = it,
                         drawerState = drawerState,
-                    )
+                    ),
+                    orientation,
                 )
             } ?: RingerViewModelState.Unavailable
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
index 2e1f82d..70e342f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/binder/VolumeDialogSettingsButtonViewBinder.kt
@@ -17,45 +17,28 @@
 package com.android.systemui.volume.dialog.settings.ui.binder
 
 import android.view.View
-import com.android.systemui.lifecycle.WindowLifecycleState
-import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.lifecycle.setSnapshotBinding
-import com.android.systemui.lifecycle.viewModel
+import android.widget.ImageButton
 import com.android.systemui.res.R
 import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
 import com.android.systemui.volume.dialog.settings.ui.viewmodel.VolumeDialogSettingsButtonViewModel
 import javax.inject.Inject
-import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 
 @VolumeDialogScope
 class VolumeDialogSettingsButtonViewBinder
 @Inject
-constructor(private val viewModelFactory: VolumeDialogSettingsButtonViewModel.Factory) {
+constructor(private val viewModel: VolumeDialogSettingsButtonViewModel) {
 
-    fun bind(view: View) {
-        with(view) {
-            val button = requireViewById<View>(R.id.volume_dialog_settings)
-            repeatWhenAttached {
-                viewModel(
-                    traceName = "VolumeDialogViewBinder",
-                    minWindowLifecycleState = WindowLifecycleState.ATTACHED,
-                    factory = { viewModelFactory.create() },
-                ) { viewModel ->
-                    setSnapshotBinding {
-                        viewModel.isVisible
-                            .onEach { isVisible ->
-                                visibility = if (isVisible) View.VISIBLE else View.GONE
-                            }
-                            .launchIn(this)
+    fun CoroutineScope.bind(view: View) {
+        val button = view.requireViewById<ImageButton>(R.id.volume_dialog_settings)
+        viewModel.isVisible
+            .onEach { isVisible -> button.visibility = if (isVisible) View.VISIBLE else View.GONE }
+            .launchIn(this)
 
-                        button.setOnClickListener { viewModel.onButtonClicked() }
-                    }
+        viewModel.icon.onEach { button.setImageDrawable(it) }.launchIn(this)
 
-                    awaitCancellation()
-                }
-            }
-        }
+        button.setOnClickListener { viewModel.onButtonClicked() }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
index 015d773..03442db 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/settings/ui/viewmodel/VolumeDialogSettingsButtonViewModel.kt
@@ -14,27 +14,206 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.volume.dialog.settings.ui.viewmodel
 
-import com.android.systemui.volume.dialog.dagger.scope.VolumeDialogScope
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.ColorFilter
+import android.graphics.drawable.Drawable
+import android.media.session.PlaybackState
+import androidx.annotation.ColorInt
+import com.airbnb.lottie.LottieComposition
+import com.airbnb.lottie.LottieCompositionFactory
+import com.airbnb.lottie.LottieDrawable
+import com.airbnb.lottie.LottieProperty
+import com.airbnb.lottie.SimpleColorFilter
+import com.airbnb.lottie.model.KeyPath
+import com.airbnb.lottie.value.LottieValueCallback
+import com.android.internal.R as internalR
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.UiBackground
+import com.android.systemui.lottie.await
+import com.android.systemui.res.R
+import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
 import com.android.systemui.volume.dialog.settings.domain.VolumeDialogSettingsButtonInteractor
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
+import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
+import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
+import com.android.systemui.volume.panel.shared.model.filterData
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.resume
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.FlowCollector
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.buffer
+import kotlinx.coroutines.flow.distinctUntilChangedBy
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.runningFold
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.transform
+import kotlinx.coroutines.suspendCancellableCoroutine
 
 class VolumeDialogSettingsButtonViewModel
-@AssistedInject
-constructor(private val interactor: VolumeDialogSettingsButtonInteractor) {
+@Inject
+constructor(
+    @Application private val context: Context,
+    @UiBackground private val uiBgCoroutineContext: CoroutineContext,
+    @VolumeDialog private val coroutineScope: CoroutineScope,
+    mediaOutputInteractor: MediaOutputInteractor,
+    private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor,
+    private val interactor: VolumeDialogSettingsButtonInteractor,
+) {
+
+    @SuppressLint("UseCompatLoadingForDrawables")
+    private val drawables: Flow<Drawables> =
+        flow {
+                val color = context.getColor(internalR.color.materialColorPrimary)
+                emit(
+                    Drawables(
+                        start =
+                            LottieCompositionFactory.fromRawRes(context, R.raw.audio_bars_in)
+                                .await()
+                                .toDrawable { setColor(color) },
+                        playing =
+                            LottieCompositionFactory.fromRawRes(context, R.raw.audio_bars_playing)
+                                .await()
+                                .toDrawable {
+                                    repeatCount = LottieDrawable.INFINITE
+                                    repeatMode = LottieDrawable.RESTART
+                                    setColor(color)
+                                },
+                        stop =
+                            LottieCompositionFactory.fromRawRes(context, R.raw.audio_bars_out)
+                                .await()
+                                .toDrawable { setColor(color) },
+                        idle = context.getDrawable(R.drawable.audio_bars_idle)!!,
+                    )
+                )
+            }
+            .buffer()
+            .flowOn(uiBgCoroutineContext)
+            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+            .filterNotNull()
 
     val isVisible = interactor.isVisible
+    val icon: Flow<Drawable> =
+        mediaOutputInteractor.defaultActiveMediaSession
+            .filterData()
+            .flatMapLatest { session ->
+                if (session == null) {
+                    flowOf(null)
+                } else {
+                    mediaDeviceSessionInteractor.playbackState(session)
+                }
+            }
+            .runningFold(null) { playbackStates: PlaybackStates?, playbackState: PlaybackState? ->
+                val isCurrentActive = playbackState?.isActive ?: false
+                if (playbackStates != null && isCurrentActive == playbackState?.isActive) {
+                    return@runningFold playbackStates
+                }
+                playbackStates?.copy(
+                    isPreviousActive = playbackStates.isCurrentActive,
+                    isCurrentActive = isCurrentActive,
+                ) ?: PlaybackStates(isPreviousActive = null, isCurrentActive = isCurrentActive)
+            }
+            .filterNotNull()
+            // only apply the most recent state if we wait for the animation.
+            .buffer(capacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
+            // distinct again because the changed state might've been dropped by the buffer
+            .distinctUntilChangedBy { it.isCurrentActive }
+            .transform { emitDrawables(it) }
+            .runningFold(null) { previous: Drawable?, current: Drawable ->
+                // wait for the previous animation to finish before starting the new one
+                // this also waits for the current loop of the playing animation to finish
+                (previous as? LottieDrawable)?.awaitFinish()
+                (current as? LottieDrawable)?.start()
+                current
+            }
+            .filterNotNull()
+
+    private suspend fun FlowCollector<Drawable>.emitDrawables(playbackStates: PlaybackStates) {
+        val animations = drawables.first()
+        val stateChanged =
+            playbackStates.isPreviousActive != null &&
+                playbackStates.isPreviousActive != playbackStates.isCurrentActive
+        if (playbackStates.isCurrentActive) {
+            if (stateChanged) {
+                emit(animations.start)
+            }
+            emit(animations.playing)
+        } else {
+            if (stateChanged) {
+                emit(animations.stop)
+            }
+            emit(animations.idle)
+        }
+    }
 
     fun onButtonClicked() {
         interactor.onButtonClicked()
     }
 
-    @VolumeDialogScope
-    @AssistedFactory
-    interface Factory {
+    private data class PlaybackStates(val isPreviousActive: Boolean?, val isCurrentActive: Boolean)
 
-        fun create(): VolumeDialogSettingsButtonViewModel
+    private data class Drawables(
+        val start: LottieDrawable,
+        val playing: LottieDrawable,
+        val stop: LottieDrawable,
+        val idle: Drawable,
+    )
+}
+
+private fun LottieComposition.toDrawable(setup: LottieDrawable.() -> Unit = {}): LottieDrawable =
+    LottieDrawable().also { drawable ->
+        drawable.composition = this
+        drawable.setup()
     }
+
+/** Suspends until current loop of the repeating animation is finished */
+private suspend fun LottieDrawable.awaitFinish() = suspendCancellableCoroutine { continuation ->
+    if (!isRunning) {
+        continuation.resume(Unit)
+        return@suspendCancellableCoroutine
+    }
+    val listener =
+        object : AnimatorListenerAdapter() {
+            override fun onAnimationRepeat(animation: Animator) {
+                continuation.resume(Unit)
+                removeAnimatorListener(this)
+            }
+
+            override fun onAnimationEnd(animation: Animator) {
+                continuation.resume(Unit)
+                removeAnimatorListener(this)
+            }
+
+            override fun onAnimationCancel(animation: Animator) {
+                continuation.resume(Unit)
+                removeAnimatorListener(this)
+            }
+        }
+    addAnimatorListener(listener)
+    continuation.invokeOnCancellation { removeAnimatorListener(listener) }
+}
+
+/**
+ * Overrides colors of the [LottieDrawable] to a specified [color]
+ *
+ * @see com.airbnb.lottie.LottieAnimationView
+ */
+private fun LottieDrawable.setColor(@ColorInt color: Int) {
+    val callback = LottieValueCallback<ColorFilter>(SimpleColorFilter(color))
+    addValueCallback(KeyPath("**"), LottieProperty.COLOR_FILTER, callback)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
index c0c525b..88af210 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/dagger/VolumeDialogSliderComponent.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.dialog.sliders.dagger
 
 import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
+import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogOverscrollViewBinder
 import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderHapticsViewBinder
 import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderTouchesViewBinder
 import com.android.systemui.volume.dialog.sliders.ui.VolumeDialogSliderViewBinder
@@ -37,6 +38,8 @@
 
     fun sliderHapticsViewBinder(): VolumeDialogSliderHapticsViewBinder
 
+    fun overscrollViewBinder(): VolumeDialogOverscrollViewBinder
+
     @Subcomponent.Factory
     interface Factory {
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
index adc2383..82885d6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/data/repository/VolumeDialogSliderTouchEventsRepository.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.volume.dialog.sliders.data.repository
 
-import android.annotation.SuppressLint
 import android.view.MotionEvent
 import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
 import javax.inject.Inject
@@ -27,7 +26,6 @@
 @VolumeDialogSliderScope
 class VolumeDialogSliderTouchEventsRepository @Inject constructor() {
 
-    @SuppressLint("SharedFlowCreation")
     private val mutableSliderTouchEvents: MutableStateFlow<MotionEvent?> = MutableStateFlow(null)
     val sliderTouchEvent: Flow<MotionEvent> = mutableSliderTouchEvents.filterNotNull()
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractor.kt
index 2967fe8..04dc80c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractor.kt
@@ -17,14 +17,18 @@
 package com.android.systemui.volume.dialog.sliders.domain.interactor
 
 import com.android.systemui.plugins.VolumeDialogController
+import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
 import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogStateInteractor
 import com.android.systemui.volume.dialog.shared.model.VolumeDialogStreamModel
 import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
 import com.android.systemui.volume.dialog.sliders.domain.model.VolumeDialogSliderType
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
 import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.stateIn
 
 /** Operates a state of particular slider of the Volume Dialog. */
 @VolumeDialogSliderScope
@@ -32,6 +36,7 @@
 @Inject
 constructor(
     private val sliderType: VolumeDialogSliderType,
+    @VolumeDialog private val coroutineScope: CoroutineScope,
     volumeDialogStateInteractor: VolumeDialogStateInteractor,
     private val volumeDialogController: VolumeDialogController,
 ) {
@@ -47,7 +52,8 @@
                     }
                 }
             }
-            .distinctUntilChanged()
+            .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+            .filterNotNull()
 
     fun setStreamVolume(userLevel: Int) {
         with(volumeDialogController) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractor.kt
index c904ac5..690f9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSlidersInteractor.kt
@@ -63,7 +63,7 @@
                 LinkedHashSet(sliderTypes)
             }
             .runningReduce { sliderTypes, newSliderTypes ->
-                newSliderTypes.apply { addAll(sliderTypes) }
+                sliderTypes.apply { addAll(newSliderTypes) }
             }
             .map { sliderTypes ->
                 VolumeDialogSlidersModel(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
new file mode 100644
index 0000000..8109b50
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogOverscrollViewBinder.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.dialog.sliders.ui
+
+import android.view.View
+import androidx.dynamicanimation.animation.FloatValueHolder
+import androidx.dynamicanimation.animation.SpringAnimation
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.systemui.res.R
+import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
+import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel
+import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogOverscrollViewModel.OverscrollEventModel
+import com.google.android.material.slider.Slider
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+
+@VolumeDialogSliderScope
+class VolumeDialogOverscrollViewBinder
+@Inject
+constructor(private val viewModel: VolumeDialogOverscrollViewModel) {
+
+    /**
+     * [viewsToAnimate] is an array of [View] to be affected by the overscroll animation. [view] is
+     * NOT animated by default.
+     */
+    fun CoroutineScope.bind(view: View, viewsToAnimate: Array<View>) {
+        val animationValueHolder = FloatValueHolder(0f)
+        val animation: SpringAnimation =
+            SpringAnimation(animationValueHolder)
+                .setSpring(
+                    SpringForce(0f).apply {
+                        stiffness = 800f
+                        dampingRatio = 0.6f
+                    }
+                )
+                .addUpdateListener { _, value, _ -> viewsToAnimate.setTranslationY(value) }
+
+        view.requireViewById<Slider>(R.id.volume_dialog_slider).addOnChangeListener { s, value, _ ->
+            viewModel.setSlider(value = value, min = s.valueFrom, max = s.valueTo)
+        }
+
+        viewModel.overscrollEvent
+            .onEach { event ->
+                when (event) {
+                    is OverscrollEventModel.Animate -> {
+                        animation.animateToFinalPosition(event.targetOffsetPx)
+                    }
+                    is OverscrollEventModel.Move -> {
+                        animation.cancel()
+                        viewsToAnimate.setTranslationY(event.touchOffsetPx)
+                        animationValueHolder.value = event.touchOffsetPx
+                    }
+                }
+            }
+            .launchIn(this)
+    }
+}
+
+private fun Array<View>.setTranslationY(translation: Float) {
+    for (viewToAnimate in this) {
+        viewToAnimate.translationY = translation
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
index f305246..a7ffcd7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSliderViewBinder.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderStateModel
 import com.android.systemui.volume.dialog.sliders.ui.viewmodel.VolumeDialogSliderViewModel
 import com.android.systemui.volume.dialog.ui.utils.JankListenerFactory
-import com.android.systemui.volume.dialog.ui.utils.awaitAnimation
+import com.android.systemui.volume.dialog.ui.utils.suspendAnimate
 import com.google.android.material.slider.LabelFormatter
 import com.google.android.material.slider.Slider
 import javax.inject.Inject
@@ -55,22 +55,21 @@
             viewModel.setStreamVolume(value.roundToInt(), fromUser)
         }
 
-        viewModel.state.onEach { it.bindToSlider(sliderView) }.launchIn(this)
+        viewModel.state.onEach { sliderView.setModel(it) }.launchIn(this)
     }
 
     @SuppressLint("UseCompatLoadingForDrawables")
-    private suspend fun VolumeDialogSliderStateModel.bindToSlider(slider: Slider) {
-        with(slider) {
-            valueFrom = minValue
-            valueTo = maxValue
-            // coerce the current value to the new value range before animating it
-            value = value.coerceIn(valueFrom, valueTo)
-            setValueAnimated(
-                value,
-                jankListenerFactory.update(this, PROGRESS_CHANGE_ANIMATION_DURATION_MS),
-            )
-            trackIconActiveEnd = context.getDrawable(iconRes)
-        }
+    private suspend fun Slider.setModel(model: VolumeDialogSliderStateModel) {
+        valueFrom = model.minValue
+        valueTo = model.maxValue
+        // coerce the current value to the new value range before animating it. This prevents
+        // animating from the value that is outside of current [valueFrom, valueTo].
+        value = value.coerceIn(valueFrom, valueTo)
+        setValueAnimated(
+            model.value,
+            jankListenerFactory.update(this, PROGRESS_CHANGE_ANIMATION_DURATION_MS),
+        )
+        trackIconActiveEnd = context.getDrawable(model.iconRes)
     }
 }
 
@@ -84,5 +83,5 @@
             interpolator = DecelerateInterpolator()
             addListener(jankListener)
         }
-        .awaitAnimation<Float> { value = it }
+        .suspendAnimate<Float> { value = it }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
index c9b5259..f066b56 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/VolumeDialogSlidersViewBinder.kt
@@ -40,9 +40,17 @@
             view.requireViewById(R.id.volume_dialog_floating_sliders_container)
         val mainSliderContainer: View =
             view.requireViewById(R.id.volume_dialog_main_slider_container)
+        val background: View = view.requireViewById(R.id.volume_dialog_background)
+        val settingsButton: View = view.requireViewById(R.id.volume_dialog_settings)
+        val ringerDrawer: View = view.requireViewById(R.id.volume_ringer_drawer)
+
         viewModel.sliders
             .onEach { uiModel ->
-                bindSlider(uiModel.sliderComponent, mainSliderContainer)
+                bindSlider(
+                    uiModel.sliderComponent,
+                    mainSliderContainer,
+                    arrayOf(mainSliderContainer, background, settingsButton, ringerDrawer),
+                )
 
                 val floatingSliderViewBinders = uiModel.floatingSliderComponent
                 floatingSlidersContainer.ensureChildCount(
@@ -50,7 +58,8 @@
                     count = floatingSliderViewBinders.size,
                 )
                 floatingSliderViewBinders.fastForEachIndexed { index, sliderComponent ->
-                    bindSlider(sliderComponent, floatingSlidersContainer.getChildAt(index))
+                    val sliderContainer = floatingSlidersContainer.getChildAt(index)
+                    bindSlider(sliderComponent, sliderContainer, arrayOf(sliderContainer))
                 }
             }
             .launchIn(this)
@@ -59,10 +68,12 @@
     private fun CoroutineScope.bindSlider(
         component: VolumeDialogSliderComponent,
         sliderContainer: View,
+        viewsToAnimate: Array<View>,
     ) {
         with(component.sliderViewBinder()) { bind(sliderContainer) }
         with(component.sliderTouchesViewBinder()) { bind(sliderContainer) }
         with(component.sliderHapticsViewBinder()) { bind(sliderContainer) }
+        with(component.overscrollViewBinder()) { bind(sliderContainer, viewsToAnimate) }
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt
new file mode 100644
index 0000000..0d41860
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/sliders/ui/viewmodel/VolumeDialogOverscrollViewModel.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.dialog.sliders.ui.viewmodel
+
+import android.content.Context
+import android.view.MotionEvent
+import android.view.animation.PathInterpolator
+import com.android.systemui.res.R
+import com.android.systemui.volume.dialog.sliders.dagger.VolumeDialogSliderScope
+import com.android.systemui.volume.dialog.sliders.domain.interactor.VolumeDialogSliderInputEventsInteractor
+import com.android.systemui.volume.dialog.sliders.shared.model.SliderInputEvent
+import javax.inject.Inject
+import kotlin.math.abs
+import kotlin.math.sign
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.transform
+
+@VolumeDialogSliderScope
+@OptIn(ExperimentalCoroutinesApi::class)
+class VolumeDialogOverscrollViewModel
+@Inject
+constructor(
+    context: Context,
+    private val inputEventsInteractor: VolumeDialogSliderInputEventsInteractor,
+) {
+
+    /**
+     * This is the ratio between the pointer distance and the dialog offset. The pointer has to
+     * travel this distance for a single point of an offset.
+     *
+     * When greater than 1 this makes the dialog to follow the touch behind.
+     */
+    private val offsetToTranslationRatio: Float = 3f
+    private val maxDeviation: Float =
+        context.resources
+            .getDimensionPixelSize(R.dimen.volume_dialog_slider_max_deviation)
+            .toFloat()
+    private val offsetInterpolator = PathInterpolator(0.15f, 0.00f, 0.20f, 1.00f)
+
+    private val sliderValue = MutableStateFlow<Slider?>(null)
+
+    val overscrollEvent: Flow<OverscrollEventModel> =
+        sliderValue
+            .filterNotNull()
+            .map { slider ->
+                when (slider.value) {
+                    slider.min -> 1f
+                    slider.max -> -1f
+                    else -> 0f
+                }
+            }
+            .distinctUntilChanged()
+            .flatMapLatest { direction ->
+                if (direction == 0f) {
+                    flowOf(OverscrollEventModel.Animate(0f))
+                } else {
+                    overscrollEvents(direction)
+                }
+            }
+
+    fun setSlider(value: Float, min: Float, max: Float) {
+        sliderValue.value = Slider(value = value, min = min, max = max)
+    }
+
+    /**
+     * Returns a flow that for each another [MotionEvent] it receives maps into a path from the
+     * first event.
+     *
+     * Emits [OverscrollEventModel.Move] that follows the [SliderInputEvent.Touch] from the pointer
+     * down position. Emits [OverscrollEventModel.Animate] when the gesture is terminated to create
+     * a spring-back effect.
+     */
+    private fun overscrollEvents(direction: Float): Flow<OverscrollEventModel> {
+        var startPosition: Float? = null
+        return inputEventsInteractor.event
+            .mapNotNull { (it as? SliderInputEvent.Touch)?.event }
+            .transform { touchEvent ->
+                // Skip events from inside the slider bounds for the case when the user adjusts
+                // slider
+                // towards max when the slider is already on max value.
+                if (touchEvent.isFinalEvent()) {
+                    startPosition = null
+                    emit(OverscrollEventModel.Animate(0f))
+                    return@transform
+                }
+                val currentStartPosition = startPosition
+                val newPosition: Float = touchEvent.rawY
+                if (currentStartPosition == null) {
+                    startPosition = newPosition
+                } else {
+                    val offset = (newPosition - currentStartPosition) / offsetToTranslationRatio
+                    val interpolatedOffset =
+                        if (areOfTheSameSign(direction, offset)) {
+                            sign(offset) *
+                                (maxDeviation *
+                                    offsetInterpolator.getInterpolation(
+                                        (abs(offset)) / maxDeviation
+                                    ))
+                        } else {
+                            0f
+                        }
+                    emit(OverscrollEventModel.Move(interpolatedOffset))
+                }
+            }
+    }
+
+    /** @return true when the [MotionEvent] indicates the end of the gesture. */
+    private fun MotionEvent.isFinalEvent(): Boolean {
+        return actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL
+    }
+
+    /** Models overscroll event */
+    sealed interface OverscrollEventModel {
+
+        /** Notifies the consumed to move by the [touchOffsetPx]. */
+        data class Move(val touchOffsetPx: Float) : OverscrollEventModel
+
+        /** Notifies the consume to animate to the [targetOffsetPx]. */
+        data class Animate(val targetOffsetPx: Float) : OverscrollEventModel
+    }
+
+    private data class Slider(val value: Float, val min: Float, val max: Float)
+}
+
+private fun areOfTheSameSign(lhs: Float, rhs: Float): Boolean =
+    when {
+        lhs < 0 -> rhs < 0
+        lhs > 0 -> rhs > 0
+        else -> rhs == 0f
+    }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/utils/SuspendAnimators.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/utils/SuspendAnimators.kt
index 10cf615..9b1d86f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/utils/SuspendAnimators.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ui/utils/SuspendAnimators.kt
@@ -22,6 +22,7 @@
 import android.view.ViewPropertyAnimator
 import androidx.dynamicanimation.animation.DynamicAnimation
 import androidx.dynamicanimation.animation.SpringAnimation
+import com.airbnb.lottie.LottieDrawable
 import kotlin.coroutines.resume
 import kotlinx.coroutines.CancellableContinuation
 import kotlinx.coroutines.suspendCancellableCoroutine
@@ -66,7 +67,7 @@
  * is cancelled.
  */
 @Suppress("UNCHECKED_CAST")
-suspend fun <T> ValueAnimator.awaitAnimation(onValueChanged: (T) -> Unit) {
+suspend fun <T> ValueAnimator.suspendAnimate(onValueChanged: (T) -> Unit) {
     suspendCancellableCoroutine { continuation ->
         addListener(
             object : AnimatorListenerAdapter() {
@@ -86,20 +87,42 @@
  * Starts spring animation and suspends until it's finished. Cancels the animation if the running
  * coroutine is cancelled.
  */
-suspend fun SpringAnimation.suspendAnimate(
-    animationUpdateListener: DynamicAnimation.OnAnimationUpdateListener? = null,
-    animationEndListener: DynamicAnimation.OnAnimationEndListener? = null,
-) = suspendCancellableCoroutine { continuation ->
-    animationUpdateListener?.let(::addUpdateListener)
-    addEndListener { animation, canceled, value, velocity ->
-        continuation.resumeIfCan(Unit)
-        animationEndListener?.onAnimationEnd(animation, canceled, value, velocity)
+suspend fun SpringAnimation.suspendAnimate(onAnimationUpdate: (Float) -> Unit) =
+    suspendCancellableCoroutine { continuation ->
+        val updateListener =
+            DynamicAnimation.OnAnimationUpdateListener { _, value, _ -> onAnimationUpdate(value) }
+        val endListener =
+            DynamicAnimation.OnAnimationEndListener { _, _, _, _ -> continuation.resumeIfCan(Unit) }
+        addUpdateListener(updateListener)
+        addEndListener(endListener)
+        animateToFinalPosition(1F)
+        continuation.invokeOnCancellation {
+            removeUpdateListener(updateListener)
+            removeEndListener(endListener)
+            cancel()
+        }
     }
-    animateToFinalPosition(1F)
+
+/**
+ * Starts the animation and suspends until it's finished. Cancels the animation if the running
+ * coroutine is cancelled.
+ */
+suspend fun LottieDrawable.suspendAnimate() = suspendCancellableCoroutine { continuation ->
+    val listener =
+        object : AnimatorListenerAdapter() {
+            override fun onAnimationEnd(animation: Animator) {
+                continuation.resumeIfCan(Unit)
+            }
+
+            override fun onAnimationCancel(animation: Animator) {
+                continuation.resumeIfCan(Unit)
+            }
+        }
+    addAnimatorListener(listener)
+    start()
     continuation.invokeOnCancellation {
-        animationUpdateListener?.let(::removeUpdateListener)
-        animationEndListener?.let(::removeEndListener)
-        cancel()
+        removeAnimatorListener(listener)
+        stop()
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
index 6e1ebc8..12e624ca 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaDeviceSessionInteractor.kt
@@ -19,10 +19,10 @@
 import android.media.session.MediaController
 import android.media.session.PlaybackState
 import com.android.settingslib.volume.data.repository.MediaControllerRepository
+import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaControllerChangeModel
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import javax.inject.Inject
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -38,7 +38,7 @@
 
 /** Allows to observe and change [MediaDeviceSession] state. */
 @OptIn(ExperimentalCoroutinesApi::class)
-@VolumePanelScope
+@SysUISingleton
 class MediaDeviceSessionInteractor
 @Inject
 constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index b3848a6..2973e11 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -24,12 +24,13 @@
 import com.android.settingslib.media.MediaDevice
 import com.android.settingslib.volume.data.repository.LocalMediaRepository
 import com.android.settingslib.volume.data.repository.MediaControllerRepository
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.util.concurrency.Execution
 import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
 import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSessions
 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
-import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
 import com.android.systemui.volume.panel.shared.model.Result
 import com.android.systemui.volume.panel.shared.model.filterData
 import com.android.systemui.volume.panel.shared.model.wrapInResult
@@ -54,13 +55,13 @@
 
 /** Provides observable models about the current media session state. */
 @OptIn(ExperimentalCoroutinesApi::class)
-@VolumePanelScope
+@SysUISingleton
 class MediaOutputInteractor
 @Inject
 constructor(
     private val localMediaRepositoryFactory: LocalMediaRepositoryFactory,
     private val packageManager: PackageManager,
-    @VolumePanelScope private val coroutineScope: CoroutineScope,
+    @Application private val coroutineScope: CoroutineScope,
     @Background private val backgroundCoroutineContext: CoroutineContext,
     mediaControllerRepository: MediaControllerRepository,
     private val mediaControllerInteractor: MediaControllerInteractor,
@@ -77,7 +78,7 @@
                     .onStart { emit(activeSessions) }
             }
             .map { getMediaControllers(it) }
-            .stateIn(coroutineScope, SharingStarted.Eagerly, MediaControllers(null, null))
+            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), MediaControllers(null, null))
 
     /** [MediaDeviceSessions] that contains currently active sessions. */
     val activeMediaDeviceSessions: Flow<MediaDeviceSessions> =
@@ -89,7 +90,11 @@
                 )
             }
             .flowOn(backgroundCoroutineContext)
-            .stateIn(coroutineScope, SharingStarted.Eagerly, MediaDeviceSessions(null, null))
+            .stateIn(
+                coroutineScope,
+                SharingStarted.WhileSubscribed(),
+                MediaDeviceSessions(null, null),
+            )
 
     /** Returns the default [MediaDeviceSession] from [activeMediaDeviceSessions] */
     val defaultActiveMediaSession: StateFlow<Result<MediaDeviceSession?>> =
@@ -104,7 +109,7 @@
             }
             .wrapInResult()
             .flowOn(backgroundCoroutineContext)
-            .stateIn(coroutineScope, SharingStarted.Eagerly, Result.Loading())
+            .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), Result.Loading())
 
     private val localMediaRepository: Flow<LocalMediaRepository> =
         defaultActiveMediaSession
diff --git a/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt b/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt
new file mode 100644
index 0000000..6b7de98
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepository.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.data.repository
+
+import android.annotation.SuppressLint
+import com.android.systemui.dagger.SysUISingleton
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+/** Repository that maintains state for the window blur effect. */
+@SysUISingleton
+class WindowRootViewBlurRepository @Inject constructor() {
+    val blurRadius = MutableStateFlow(0)
+
+    val isBlurOpaque = MutableStateFlow(false)
+
+    @SuppressLint("SharedFlowCreation") val onBlurApplied = MutableSharedFlow<Int>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
new file mode 100644
index 0000000..fee32b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractor.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.domain.interactor
+
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.window.data.repository.WindowRootViewBlurRepository
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/**
+ * Interactor that provides the blur state for the window root view
+ * [com.android.systemui.scene.ui.view.WindowRootView]
+ */
+@SysUISingleton
+class WindowRootViewBlurInteractor
+@Inject
+constructor(
+    private val keyguardInteractor: KeyguardInteractor,
+    private val repository: WindowRootViewBlurRepository,
+) {
+
+    /**
+     * Invoked by the view after blur of [appliedBlurRadius] was successfully applied on the window
+     * root view.
+     */
+    suspend fun onBlurApplied(appliedBlurRadius: Int) {
+        repository.onBlurApplied.emit(appliedBlurRadius)
+    }
+
+    /** Radius of blur to be applied on the window root view. */
+    val blurRadius: StateFlow<Int> = repository.blurRadius.asStateFlow()
+
+    /** Whether the blur applied is opaque or transparent. */
+    val isBlurOpaque: StateFlow<Boolean> = repository.isBlurOpaque.asStateFlow()
+
+    /**
+     * Emits the applied blur radius whenever blur is successfully applied to the window root view.
+     */
+    val onBlurAppliedEvent: Flow<Int> = repository.onBlurApplied
+
+    /**
+     * Request to apply blur while on bouncer, this takes precedence over other blurs (from
+     * shade).
+     */
+    fun requestBlurForBouncer(blurRadius: Int) {
+        repository.isBlurOpaque.value = false
+        repository.blurRadius.value = blurRadius
+    }
+
+    /**
+     * Method that requests blur to be applied on window root view. It is applied only when other
+     * blurs are not applied.
+     *
+     * This method is present to temporarily support the blur for notification shade, ideally shade
+     * should expose state that is used by this interactor to determine the blur that has to be
+     * applied.
+     *
+     * @return whether the request for blur was processed or not.
+     */
+    fun requestBlurForShade(blurRadius: Int, opaque: Boolean): Boolean {
+        if (keyguardInteractor.primaryBouncerShowing.value) {
+            return false
+        }
+        Log.d(TAG, "requestingBlurForShade for $blurRadius $opaque")
+        repository.blurRadius.value = blurRadius
+        repository.isBlurOpaque.value = opaque
+        return true
+    }
+
+    companion object {
+        const val TAG = "WindowRootViewBlurInteractor"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
new file mode 100644
index 0000000..2491ca7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/ui/WindowRootViewBinder.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.ui
+
+import android.util.Log
+import android.view.Choreographer
+import android.view.Choreographer.FrameCallback
+import com.android.systemui.lifecycle.WindowLifecycleState
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.lifecycle.viewModel
+import com.android.systemui.scene.ui.view.WindowRootView
+import com.android.systemui.statusbar.BlurUtils
+import com.android.systemui.window.flag.WindowBlurFlag
+import com.android.systemui.window.ui.viewmodel.WindowRootViewModel
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.launch
+
+/**
+ * View binder that wires up window level UI transformations like blur to the [WindowRootView]
+ * instance.
+ */
+object WindowRootViewBinder {
+    private const val TAG = "WindowRootViewBinder"
+
+    fun bind(
+        view: WindowRootView,
+        viewModelFactory: WindowRootViewModel.Factory,
+        blurUtils: BlurUtils?,
+        choreographer: Choreographer?,
+    ) {
+        if (!WindowBlurFlag.isEnabled) return
+        if (blurUtils == null || choreographer == null) return
+
+        view.repeatWhenAttached {
+            Log.d(TAG, "Binding root view")
+            var frameCallbackPendingExecution: FrameCallback? = null
+            val viewRootImpl = view.rootView.viewRootImpl
+            view.viewModel(
+                minWindowLifecycleState = WindowLifecycleState.ATTACHED,
+                factory = { viewModelFactory.create() },
+                traceName = "WindowRootViewBinder#bind",
+            ) { viewModel ->
+                try {
+                    Log.d(TAG, "Launching coroutines that update window root view state")
+                    launch {
+                        viewModel.blurState
+                            .filter { it.radius >= 0 }
+                            .collect { blurState ->
+                                val newFrameCallback = FrameCallback {
+                                    frameCallbackPendingExecution = null
+                                    blurUtils.applyBlur(
+                                        viewRootImpl,
+                                        blurState.radius,
+                                        blurState.isOpaque,
+                                    )
+                                    viewModel.onBlurApplied(blurState.radius)
+                                }
+                                blurUtils.prepareBlur(viewRootImpl, blurState.radius)
+                                if (frameCallbackPendingExecution != null) {
+                                    choreographer.removeFrameCallback(frameCallbackPendingExecution)
+                                }
+                                frameCallbackPendingExecution = newFrameCallback
+                                choreographer.postFrameCallback(newFrameCallback)
+                            }
+                    }
+                    awaitCancellation()
+                } finally {
+                    Log.d(TAG, "Wrapped up coroutines that update window root view state")
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt
new file mode 100644
index 0000000..199d02d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModel.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.ui.viewmodel
+
+import android.os.Build
+import android.util.Log
+import com.android.app.tracing.coroutines.launchTraced
+import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
+
+typealias BlurAppliedUiEvent = Int
+
+/** View model for window root view. */
+class WindowRootViewModel
+@AssistedInject
+constructor(
+    private val primaryBouncerTransitions: Set<@JvmSuppressWildcards PrimaryBouncerTransition>,
+    private val blurInteractor: WindowRootViewBlurInteractor,
+) : ExclusiveActivatable() {
+
+    private val blurEvents = Channel<BlurAppliedUiEvent>(Channel.BUFFERED)
+    private val _blurState = MutableStateFlow(BlurState(0, false))
+    val blurState = _blurState.asStateFlow()
+
+    override suspend fun onActivated(): Nothing {
+        coroutineScope {
+            launchTraced("WindowRootViewModel#blurEvents") {
+                for (event in blurEvents) {
+                    if (isLoggable) {
+                        Log.d(TAG, "blur applied for $event")
+                    }
+                    blurInteractor.onBlurApplied(event)
+                }
+            }
+
+            launchTraced("WindowRootViewModel#blurState") {
+                combine(blurInteractor.blurRadius, blurInteractor.isBlurOpaque, ::BlurState)
+                    .collect { _blurState.value = it }
+            }
+
+            launchTraced("WindowRootViewModel#bouncerTransitions") {
+                primaryBouncerTransitions
+                    .map { transition ->
+                        transition.windowBlurRadius.onEach { blurRadius ->
+                            if (isLoggable) {
+                                Log.d(
+                                    TAG,
+                                    "${transition.javaClass.simpleName} windowBlurRadius $blurRadius",
+                                )
+                            }
+                        }
+                    }
+                    .merge()
+                    .collect { blurRadius ->
+                        blurInteractor.requestBlurForBouncer(blurRadius.toInt())
+                    }
+            }
+        }
+        awaitCancellation()
+    }
+
+    fun onBlurApplied(blurRadius: Int) {
+        blurEvents.trySend(blurRadius)
+    }
+
+    @AssistedFactory
+    interface Factory {
+        fun create(): WindowRootViewModel
+    }
+
+    private companion object {
+        const val TAG = "WindowRootViewModel"
+        val isLoggable = Log.isLoggable(TAG, Log.DEBUG) || Build.isDebuggable()
+    }
+}
+
+/**
+ * @property radius Radius of blur to be applied on the window root view.
+ * @property isOpaque Whether the blur applied is opaque or transparent.
+ */
+data class BlurState(val radius: Int, val isOpaque: Boolean)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index a41725f..4abbbac 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.settingslib.notification.modes.TestModeBuilder.MANUAL_DND_INACTIVE
-import com.android.systemui.Flags as AConfigFlags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.flags.Flags
@@ -299,20 +298,6 @@
         }
 
     @Test
-    @DisableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun keyguardCallback_visibilityChanged_clockDozeCalled() =
-        runBlocking(IMMEDIATE) {
-            val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
-            verify(keyguardUpdateMonitor).registerCallback(capture(captor))
-
-            captor.value.onKeyguardVisibilityChanged(true)
-            verify(animations, never()).doze(0f)
-
-            captor.value.onKeyguardVisibilityChanged(false)
-            verify(animations, times(2)).doze(0f)
-        }
-
-    @Test
     fun keyguardCallback_timeFormat_clockNotified() =
         runBlocking(IMMEDIATE) {
             val captor = argumentCaptor<KeyguardUpdateMonitorCallback>()
@@ -344,19 +329,6 @@
         }
 
     @Test
-    fun keyguardCallback_verifyKeyguardChanged() =
-        runBlocking(IMMEDIATE) {
-            val job = underTest.listenForDozeAmount(this)
-            repository.setDozeAmount(0.4f)
-
-            yield()
-
-            verify(animations, times(2)).doze(0.4f)
-
-            job.cancel()
-        }
-
-    @Test
     fun listenForDozeAmountTransition_updatesClockDozeAmount() =
         runBlocking(IMMEDIATE) {
             val transitionStep = MutableStateFlow(TransitionStep())
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
deleted file mode 100644
index 8e441a3..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-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 static org.mockito.Mockito.when;
-
-import android.animation.AnimatorTestRule;
-import android.platform.test.annotations.DisableFlags;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.app.animation.Interpolators;
-import com.android.systemui.Flags;
-import com.android.systemui.animation.ViewHierarchyAnimator;
-import com.android.systemui.plugins.clocks.ClockConfig;
-import com.android.systemui.plugins.clocks.ClockController;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.lang.reflect.Field;
-
-@SmallTest
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@RunWith(AndroidTestingRunner.class)
-public class KeyguardStatusViewControllerTest extends KeyguardStatusViewControllerBaseTest {
-
-    @Rule
-    public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(this);
-
-    @Test
-    public void dozeTimeTick_updatesSlice() {
-        mController.dozeTimeTick();
-        verify(mKeyguardSliceViewController).refresh();
-    }
-
-    @Test
-    public void dozeTimeTick_updatesClock() {
-        mController.dozeTimeTick();
-        verify(mKeyguardClockSwitchController).refresh();
-    }
-
-    @Test
-    public void setTranslationYExcludingMedia_forwardsCallToView() {
-        float translationY = 123f;
-
-        mController.setTranslationY(translationY, /* excludeMedia= */true);
-
-        verify(mKeyguardStatusView).setChildrenTranslationY(translationY, /* excludeMedia= */true);
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void onLocaleListChangedNotifiesClockSwitchController() {
-        ArgumentCaptor<ConfigurationListener> configurationListenerArgumentCaptor =
-                ArgumentCaptor.forClass(ConfigurationListener.class);
-
-        mController.onViewAttached();
-        verify(mConfigurationController).addCallback(configurationListenerArgumentCaptor.capture());
-
-        configurationListenerArgumentCaptor.getValue().onLocaleListChanged();
-        verify(mKeyguardClockSwitchController).onLocaleListChanged();
-    }
-
-    @Test
-    public void updatePosition_primaryClockAnimation() {
-        ClockController mockClock = mock(ClockController.class);
-        when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
-        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", false, true, false));
-
-        mController.updatePosition(10, 15, 20f, true);
-
-        verify(mControllerMock).setProperty(AnimatableProperty.Y, 15f, true);
-        verify(mKeyguardClockSwitchController).updatePosition(
-                10, 20f, KeyguardStatusViewController.CLOCK_ANIMATION_PROPERTIES, true);
-        verify(mControllerMock).setProperty(AnimatableProperty.SCALE_X, 1f, true);
-        verify(mControllerMock).setProperty(AnimatableProperty.SCALE_Y, 1f, true);
-    }
-
-    @Test
-    public void updatePosition_alternateClockAnimation() {
-        ClockController mockClock = mock(ClockController.class);
-        when(mKeyguardClockSwitchController.getClock()).thenReturn(mockClock);
-        when(mockClock.getConfig()).thenReturn(new ClockConfig("MOCK", "", "", true, true, false));
-
-        mController.updatePosition(10, 15, 20f, true);
-
-        verify(mControllerMock).setProperty(AnimatableProperty.Y, 15f, true);
-        verify(mKeyguardClockSwitchController).updatePosition(
-                10, 1f, KeyguardStatusViewController.CLOCK_ANIMATION_PROPERTIES, true);
-        verify(mControllerMock).setProperty(AnimatableProperty.SCALE_X, 20f, true);
-        verify(mControllerMock).setProperty(AnimatableProperty.SCALE_Y, 20f, true);
-    }
-
-    @Test
-    public void splitShadeEnabledPassedToClockSwitchController() {
-        mController.setSplitShadeEnabled(true);
-        verify(mKeyguardClockSwitchController, times(1)).setSplitShadeEnabled(true);
-        verify(mKeyguardClockSwitchController, times(0)).setSplitShadeEnabled(false);
-    }
-
-    @Test
-    public void splitShadeDisabledPassedToClockSwitchController() {
-        mController.setSplitShadeEnabled(false);
-        verify(mKeyguardClockSwitchController, times(1)).setSplitShadeEnabled(false);
-        verify(mKeyguardClockSwitchController, times(0)).setSplitShadeEnabled(true);
-    }
-
-    @Test
-    public void onInit_addsOnLayoutChangeListenerToClockSwitch() {
-        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
-                mMediaHostContainer);
-
-        mController.onInit();
-
-        ArgumentCaptor<View.OnLayoutChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mKeyguardClockSwitch).addOnLayoutChangeListener(captor.capture());
-    }
-
-    @Test
-    public void clockSwitchHeightChanged_animatesMediaHostContainer() {
-        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
-                mMediaHostContainer);
-
-        mController.onInit();
-
-        ArgumentCaptor<View.OnLayoutChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mKeyguardClockSwitch).addOnLayoutChangeListener(captor.capture());
-
-        // Above here is the same as `onInit_addsOnLayoutChangeListenerToClockSwitch`.
-        // Below here is the actual test.
-
-        ViewHierarchyAnimator.Companion animator = ViewHierarchyAnimator.Companion;
-        ViewHierarchyAnimator.Companion spiedAnimator = spy(animator);
-        setCompanion(spiedAnimator);
-
-        View.OnLayoutChangeListener listener = captor.getValue();
-
-        mController.setSplitShadeEnabled(true);
-        when(mKeyguardClockSwitch.getSplitShadeCentered()).thenReturn(false);
-        when(mKeyguardUpdateMonitor.isKeyguardVisible()).thenReturn(true);
-        when(mMediaHostContainer.getVisibility()).thenReturn(View.VISIBLE);
-        when(mMediaHostContainer.getHeight()).thenReturn(200);
-
-        when(mKeyguardClockSwitch.getHeight()).thenReturn(0);
-        listener.onLayoutChange(mKeyguardClockSwitch, /* left= */ 0, /* top= */ 0, /* right= */
-                0, /* bottom= */ 0, /* oldLeft= */ 0, /* oldTop= */ 0, /* oldRight= */
-                0, /* oldBottom = */ 200);
-        verify(spiedAnimator).animateNextUpdate(mMediaHostContainer,
-                Interpolators.STANDARD, /* duration= */ 500L, /* animateChildren= */ false);
-
-        // Resets ViewHierarchyAnimator.Companion to its original value
-        setCompanion(animator);
-    }
-
-    @Test
-    public void clockSwitchHeightNotChanged_doesNotAnimateMediaOutputContainer() {
-        when(mKeyguardStatusView.findViewById(R.id.status_view_media_container)).thenReturn(
-                mMediaHostContainer);
-
-        mController.onInit();
-
-        ArgumentCaptor<View.OnLayoutChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mKeyguardClockSwitch).addOnLayoutChangeListener(captor.capture());
-
-        // Above here is the same as `onInit_addsOnLayoutChangeListenerToClockSwitch`.
-        // Below here is the actual test.
-
-        ViewHierarchyAnimator.Companion animator = ViewHierarchyAnimator.Companion;
-        ViewHierarchyAnimator.Companion spiedAnimator = spy(animator);
-        setCompanion(spiedAnimator);
-
-        View.OnLayoutChangeListener listener = captor.getValue();
-
-        mController.setSplitShadeEnabled(true);
-        when(mKeyguardClockSwitch.getSplitShadeCentered()).thenReturn(false);
-        when(mKeyguardUpdateMonitor.isKeyguardVisible()).thenReturn(true);
-        when(mMediaHostContainer.getVisibility()).thenReturn(View.VISIBLE);
-        when(mMediaHostContainer.getHeight()).thenReturn(200);
-
-        when(mKeyguardClockSwitch.getHeight()).thenReturn(200);
-        listener.onLayoutChange(mKeyguardClockSwitch, /* left= */ 0, /* top= */ 0, /* right= */
-                0, /* bottom= */ 0, /* oldLeft= */ 0, /* oldTop= */ 0, /* oldRight= */
-                0, /* oldBottom = */ 200);
-        verify(spiedAnimator, never()).animateNextUpdate(any(), any(), anyLong(), anyBoolean());
-
-        // Resets ViewHierarchyAnimator.Companion to its original value
-        setCompanion(animator);
-    }
-
-    private void setCompanion(ViewHierarchyAnimator.Companion companion) {
-        try {
-            Field field = ViewHierarchyAnimator.class.getDeclaredField("Companion");
-            field.setAccessible(true);
-            field.set(null, companion);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Test
-    @DisableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    public void statusAreaHeightChange_animatesHeightOutputChange() {
-        // Init & Capture Layout Listener
-        mController.onInit();
-        mController.onViewAttached();
-
-        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
-        ArgumentCaptor<View.OnLayoutChangeListener> captor =
-                ArgumentCaptor.forClass(View.OnLayoutChangeListener.class);
-        verify(mKeyguardStatusAreaView).addOnLayoutChangeListener(captor.capture());
-        View.OnLayoutChangeListener listener = captor.getValue();
-
-        // Setup and validate initial height
-        when(mKeyguardStatusView.getHeight()).thenReturn(200);
-        when(mKeyguardClockSwitchController.getNotificationIconAreaHeight()).thenReturn(10);
-        assertEquals(190, mController.getLockscreenHeight());
-
-        // Trigger Change and validate value unchanged immediately
-        when(mKeyguardStatusAreaView.getHeight()).thenReturn(100);
-        when(mKeyguardStatusView.getHeight()).thenReturn(300);      // Include child height
-        listener.onLayoutChange(mKeyguardStatusAreaView,
-            /* new layout */ 100, 300, 200, 400,
-            /* old layout */ 100, 300, 200, 300);
-        assertEquals(190, mController.getLockscreenHeight());
-
-        // Complete animation, validate height increased
-        mAnimatorTestRule.advanceTimeBy(200);
-        assertEquals(290, mController.getLockscreenHeight());
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
index 5e9f2a2..9d9fb9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/FullscreenMagnificationControllerTest.java
@@ -56,6 +56,7 @@
 import android.window.InputTransferToken;
 
 import androidx.annotation.NonNull;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.Flags;
@@ -77,6 +78,7 @@
 @SmallTest
 @TestableLooper.RunWithLooper
 @RunWith(AndroidTestingRunner.class)
+@FlakyTest(bugId = 385115361)
 public class FullscreenMagnificationControllerTest extends SysuiTestCase {
     private static final long ANIMATION_DURATION_MS = 100L;
     private static final long WAIT_TIMEOUT_S = 5L * HW_TIMEOUT_MULTIPLIER;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
index 4aaa82e..37eb148 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
@@ -14,6 +14,8 @@
 import android.view.IRemoteAnimationFinishedCallback
 import android.view.RemoteAnimationAdapter
 import android.view.RemoteAnimationTarget
+import android.view.RemoteAnimationTarget.MODE_CLOSING
+import android.view.RemoteAnimationTarget.MODE_OPENING
 import android.view.SurfaceControl
 import android.view.ViewGroup
 import android.view.WindowManager.TRANSIT_NONE
@@ -36,10 +38,6 @@
 import junit.framework.AssertionFailedError
 import kotlin.concurrent.thread
 import kotlin.test.assertEquals
-import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
 import org.junit.After
 import org.junit.Assert.assertThrows
 import org.junit.Before
@@ -49,6 +47,7 @@
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.Mock
+import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
@@ -215,22 +214,12 @@
     )
     @Test
     fun registersLongLivedTransition() {
-        activityTransitionAnimator.register(
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie =
-                    ActivityTransitionAnimator.TransitionCookie("test_cookie_1")
-                override val component = ComponentName("com.test.package", "Test1")
-            }
-        )
+        var factory = controllerFactory()
+        activityTransitionAnimator.register(factory.cookie, factory)
         assertEquals(2, testShellTransitions.remotes.size)
 
-        activityTransitionAnimator.register(
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie =
-                    ActivityTransitionAnimator.TransitionCookie("test_cookie_2")
-                override val component = ComponentName("com.test.package", "Test2")
-            }
-        )
+        factory = controllerFactory()
+        activityTransitionAnimator.register(factory.cookie, factory)
         assertEquals(4, testShellTransitions.remotes.size)
     }
 
@@ -241,20 +230,12 @@
     @Test
     fun registersLongLivedTransitionOverridingPreviousRegistration() {
         val cookie = ActivityTransitionAnimator.TransitionCookie("test_cookie")
-        activityTransitionAnimator.register(
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie = cookie
-                override val component = ComponentName("com.test.package", "Test1")
-            }
-        )
+        var factory = controllerFactory(cookie)
+        activityTransitionAnimator.register(cookie, factory)
         val transitions = testShellTransitions.remotes.values.toList()
 
-        activityTransitionAnimator.register(
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie = cookie
-                override val component = ComponentName("com.test.package", "Test2")
-            }
-        )
+        factory = controllerFactory(cookie)
+        activityTransitionAnimator.register(cookie, factory)
         assertEquals(2, testShellTransitions.remotes.size)
         for (transition in transitions) {
             assertThat(testShellTransitions.remotes.values).doesNotContain(transition)
@@ -264,38 +245,19 @@
     @DisableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED)
     @Test
     fun doesNotRegisterLongLivedTransitionIfFlagIsDisabled() {
-        val controller =
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie =
-                    ActivityTransitionAnimator.TransitionCookie("test_cookie")
-                override val component = ComponentName("com.test.package", "Test")
-            }
+        val factory = controllerFactory(component = null)
         assertThrows(IllegalStateException::class.java) {
-            activityTransitionAnimator.register(controller)
+            activityTransitionAnimator.register(factory.cookie, factory)
         }
     }
 
     @EnableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LONG_LIVED)
     @Test
     fun doesNotRegisterLongLivedTransitionIfMissingRequiredProperties() {
-        // No TransitionCookie
-        val controllerWithoutCookie =
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie = null
-            }
-        assertThrows(IllegalStateException::class.java) {
-            activityTransitionAnimator.register(controllerWithoutCookie)
-        }
-
         // No ComponentName
-        val controllerWithoutComponent =
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie =
-                    ActivityTransitionAnimator.TransitionCookie("test_cookie")
-                override val component = null
-            }
+        var factory = controllerFactory(component = null)
         assertThrows(IllegalStateException::class.java) {
-            activityTransitionAnimator.register(controllerWithoutComponent)
+            activityTransitionAnimator.register(factory.cookie, factory)
         }
 
         // No TransitionRegister
@@ -307,14 +269,9 @@
                 testTransitionAnimator,
                 disableWmTimeout = true,
             )
-        val validController =
-            object : DelegateTransitionAnimatorController(controller) {
-                override val transitionCookie =
-                    ActivityTransitionAnimator.TransitionCookie("test_cookie")
-                override val component = ComponentName("com.test.package", "Test")
-            }
+        factory = controllerFactory()
         assertThrows(IllegalStateException::class.java) {
-            activityTransitionAnimator.register(validController)
+            activityTransitionAnimator.register(factory.cookie, factory)
         }
     }
 
@@ -324,18 +281,12 @@
     )
     @Test
     fun unregistersLongLivedTransition() {
-
         val cookies = arrayOfNulls<ActivityTransitionAnimator.TransitionCookie>(3)
 
         for (index in 0 until 3) {
-            cookies[index] = ActivityTransitionAnimator.TransitionCookie("test_cookie_$index")
-
-            val controller =
-                object : DelegateTransitionAnimatorController(controller) {
-                    override val transitionCookie = cookies[index]
-                    override val component = ComponentName("foo.bar", "Foobar")
-                }
-            activityTransitionAnimator.register(controller)
+            cookies[index] = mock(ActivityTransitionAnimator.TransitionCookie::class.java)
+            val factory = controllerFactory(cookies[index]!!)
+            activityTransitionAnimator.register(factory.cookie, factory)
         }
 
         activityTransitionAnimator.unregister(cookies[0]!!)
@@ -350,7 +301,7 @@
 
     @Test
     fun doesNotStartIfAnimationIsCancelled() {
-        val runner = activityTransitionAnimator.createRunner(controller)
+        val runner = activityTransitionAnimator.createEphemeralRunner(controller)
         runner.onAnimationCancelled()
         runner.onAnimationStart(TRANSIT_NONE, emptyArray(), emptyArray(), emptyArray(), iCallback)
 
@@ -364,7 +315,7 @@
 
     @Test
     fun cancelsIfNoOpeningWindowIsFound() {
-        val runner = activityTransitionAnimator.createRunner(controller)
+        val runner = activityTransitionAnimator.createEphemeralRunner(controller)
         runner.onAnimationStart(TRANSIT_NONE, emptyArray(), emptyArray(), emptyArray(), iCallback)
 
         waitForIdleSync()
@@ -377,7 +328,7 @@
 
     @Test
     fun startsAnimationIfWindowIsOpening() {
-        val runner = activityTransitionAnimator.createRunner(controller)
+        val runner = activityTransitionAnimator.createEphemeralRunner(controller)
         runner.onAnimationStart(
             TRANSIT_NONE,
             arrayOf(fakeWindow()),
@@ -404,7 +355,8 @@
     @Test
     fun creatingRunnerWithLazyInitializationThrows_whenTheFlagsAreDisabled() {
         assertThrows(IllegalStateException::class.java) {
-            activityTransitionAnimator.createRunner(controller, longLived = true)
+            val factory = controllerFactory()
+            activityTransitionAnimator.createLongLivedRunner(factory, forLaunch = true)
         }
     }
 
@@ -414,7 +366,8 @@
     )
     @Test
     fun runnerCreatesDelegateLazily_whenPostingTimeouts() {
-        val runner = activityTransitionAnimator.createRunner(controller, longLived = true)
+        val factory = controllerFactory()
+        val runner = activityTransitionAnimator.createLongLivedRunner(factory, forLaunch = true)
         assertNull(runner.delegate)
         runner.postTimeouts()
         assertNotNull(runner.delegate)
@@ -426,29 +379,29 @@
     )
     @Test
     fun runnerCreatesDelegateLazily_onAnimationStart() {
-        val runner = activityTransitionAnimator.createRunner(controller, longLived = true)
+        val factory = controllerFactory()
+        val runner = activityTransitionAnimator.createLongLivedRunner(factory, forLaunch = true)
         assertNull(runner.delegate)
 
-        // The delegate is cleaned up after execution (which happens in another thread), so what we
-        // do instead is check if it becomes non-null at any point with a 1 second timeout. This
-        // will tell us that takeOverWithAnimation() triggered the lazy initialization.
         var delegateInitialized = false
-        runBlocking {
-            val initChecker = launch {
-                withTimeout(1.seconds) {
-                    while (runner.delegate == null) continue
+        activityTransitionAnimator.addListener(
+            object : ActivityTransitionAnimator.Listener {
+                override fun onTransitionAnimationStart() {
+                    // This is called iff the delegate was initialized, so it's a good proxy for
+                    // checking the initialization.
                     delegateInitialized = true
                 }
             }
-            runner.onAnimationStart(
-                TRANSIT_NONE,
-                arrayOf(fakeWindow()),
-                emptyArray(),
-                emptyArray(),
-                iCallback,
-            )
-            initChecker.join()
-        }
+        )
+        runner.onAnimationStart(
+            TRANSIT_NONE,
+            arrayOf(fakeWindow()),
+            emptyArray(),
+            emptyArray(),
+            iCallback,
+        )
+
+        waitForIdleSync()
         assertTrue(delegateInitialized)
     }
 
@@ -458,28 +411,28 @@
     )
     @Test
     fun runnerCreatesDelegateLazily_onAnimationTakeover() {
-        val runner = activityTransitionAnimator.createRunner(controller, longLived = true)
+        val factory = controllerFactory()
+        val runner = activityTransitionAnimator.createLongLivedRunner(factory, forLaunch = false)
         assertNull(runner.delegate)
 
-        // The delegate is cleaned up after execution (which happens in another thread), so what we
-        // do instead is check if it becomes non-null at any point with a 1 second timeout. This
-        // will tell us that takeOverWithAnimation() triggered the lazy initialization.
         var delegateInitialized = false
-        runBlocking {
-            val initChecker = launch {
-                withTimeout(1.seconds) {
-                    while (runner.delegate == null) continue
+        activityTransitionAnimator.addListener(
+            object : ActivityTransitionAnimator.Listener {
+                override fun onTransitionAnimationStart() {
+                    // This is called iff the delegate was initialized, so it's a good proxy for
+                    // checking the initialization.
                     delegateInitialized = true
                 }
             }
-            runner.takeOverAnimation(
-                arrayOf(fakeWindow()),
-                arrayOf(WindowAnimationState()),
-                SurfaceControl.Transaction(),
-                iCallback,
-            )
-            initChecker.join()
-        }
+        )
+        runner.takeOverAnimation(
+            arrayOf(fakeWindow(MODE_CLOSING)),
+            arrayOf(WindowAnimationState()),
+            SurfaceControl.Transaction(),
+            iCallback,
+        )
+
+        waitForIdleSync()
         assertTrue(delegateInitialized)
     }
 
@@ -489,7 +442,7 @@
     )
     @Test
     fun animationTakeoverThrows_whenTheFlagsAreDisabled() {
-        val runner = activityTransitionAnimator.createRunner(controller, longLived = false)
+        val runner = activityTransitionAnimator.createEphemeralRunner(controller)
         assertThrows(IllegalStateException::class.java) {
             runner.takeOverAnimation(
                 arrayOf(fakeWindow()),
@@ -506,14 +459,28 @@
     )
     @Test
     fun disposeRunner_delegateDereferenced() {
-        val runner = activityTransitionAnimator.createRunner(controller)
+        val runner = activityTransitionAnimator.createEphemeralRunner(controller)
         assertNotNull(runner.delegate)
         runner.dispose()
         waitForIdleSync()
         assertNull(runner.delegate)
     }
 
-    private fun fakeWindow(): RemoteAnimationTarget {
+    private fun controllerFactory(
+        cookie: ActivityTransitionAnimator.TransitionCookie =
+            mock(ActivityTransitionAnimator.TransitionCookie::class.java),
+        component: ComponentName? = mock(ComponentName::class.java),
+    ): ActivityTransitionAnimator.ControllerFactory {
+        return object : ActivityTransitionAnimator.ControllerFactory(cookie, component) {
+            override fun createController(forLaunch: Boolean) =
+                object : DelegateTransitionAnimatorController(controller) {
+                    override val isLaunching: Boolean
+                        get() = forLaunch
+                }
+        }
+    }
+
+    private fun fakeWindow(mode: Int = MODE_OPENING): RemoteAnimationTarget {
         val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
         val taskInfo = ActivityManager.RunningTaskInfo()
         taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
@@ -521,7 +488,7 @@
 
         return RemoteAnimationTarget(
             0,
-            RemoteAnimationTarget.MODE_OPENING,
+            mode,
             SurfaceControl(),
             false,
             Rect(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt
index fb0fd23..6bfd080 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegateTest.kt
@@ -34,8 +34,10 @@
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.model.SysUiState
 import com.android.systemui.res.R
+import com.android.systemui.shade.data.repository.shadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.phone.SystemUIDialogManager
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
@@ -82,7 +84,7 @@
     private val uiProperties =
         BluetoothTileDialogViewModel.UiProperties.build(
             isBluetoothEnabled = ENABLED,
-            isAutoOnToggleFeatureAvailable = ENABLED
+            isAutoOnToggleFeatureAvailable = ENABLED,
         )
     @Mock private lateinit var sysuiDialogFactory: SystemUIDialog.Factory
     @Mock private lateinit var dialogManager: SystemUIDialogManager
@@ -98,6 +100,8 @@
     private lateinit var mBluetoothTileDialogDelegate: BluetoothTileDialogDelegate
     private lateinit var deviceItem: DeviceItem
 
+    private val kosmos = testKosmos()
+
     @Before
     fun setUp() {
         scheduler = TestCoroutineScheduler()
@@ -116,10 +120,16 @@
                 fakeSystemClock,
                 uiEventLogger,
                 logger,
-                sysuiDialogFactory
+                sysuiDialogFactory,
+                kosmos.shadeDialogContextInteractor,
             )
 
-        whenever(sysuiDialogFactory.create(any(SystemUIDialog.Delegate::class.java))).thenAnswer {
+        whenever(
+            sysuiDialogFactory.create(
+                any(SystemUIDialog.Delegate::class.java),
+                any()
+            )
+        ).thenAnswer {
             SystemUIDialog(
                 mContext,
                 0,
@@ -128,7 +138,7 @@
                 sysuiState,
                 fakeBroadcastDispatcher,
                 dialogTransitionAnimator,
-                it.getArgument(0)
+                it.getArgument(0),
             )
         }
 
@@ -140,7 +150,7 @@
                 deviceName = DEVICE_NAME,
                 connectionSummary = DEVICE_CONNECTION_SUMMARY,
                 iconWithDescription = icon,
-                background = null
+                background = null,
             )
         `when`(cachedBluetoothDevice.isBusy).thenReturn(false)
     }
@@ -169,7 +179,7 @@
                 dialog,
                 listOf(deviceItem),
                 showSeeAll = false,
-                showPairNewDevice = false
+                showPairNewDevice = false,
             )
 
             val recyclerView = dialog.requireViewById<RecyclerView>(R.id.device_list)
@@ -217,6 +227,7 @@
                     uiEventLogger,
                     logger,
                     sysuiDialogFactory,
+                    kosmos.shadeDialogContextInteractor,
                 )
                 .Adapter(bluetoothTileDialogCallback)
                 .DeviceItemViewHolder(view)
@@ -238,7 +249,7 @@
                 dialog,
                 listOf(deviceItem),
                 showSeeAll = false,
-                showPairNewDevice = true
+                showPairNewDevice = true,
             )
 
             val seeAllButton = dialog.requireViewById<View>(R.id.see_all_button)
@@ -272,6 +283,7 @@
                         uiEventLogger,
                         logger,
                         sysuiDialogFactory,
+                        kosmos.shadeDialogContextInteractor,
                     )
                     .createDialog()
             dialog.show()
@@ -295,6 +307,7 @@
                         uiEventLogger,
                         logger,
                         sysuiDialogFactory,
+                        kosmos.shadeDialogContextInteractor,
                     )
                     .createDialog()
             dialog.show()
@@ -318,6 +331,7 @@
                         uiEventLogger,
                         logger,
                         sysuiDialogFactory,
+                        kosmos.shadeDialogContextInteractor,
                     )
                     .createDialog()
             dialog.show()
@@ -339,7 +353,7 @@
                 dialog,
                 visibility = VISIBLE,
                 label = null,
-                isActive = true
+                isActive = true,
             )
 
             val audioSharingButton = dialog.requireViewById<View>(R.id.audio_sharing_button)
@@ -361,7 +375,7 @@
                 dialog,
                 visibility = VISIBLE,
                 label = null,
-                isActive = false
+                isActive = false,
             )
 
             val audioSharingButton = dialog.requireViewById<View>(R.id.audio_sharing_button)
@@ -383,7 +397,7 @@
                 dialog,
                 visibility = GONE,
                 label = null,
-                isActive = false
+                isActive = false,
             )
 
             val audioSharingButton = dialog.requireViewById<View>(R.id.audio_sharing_button)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
similarity index 97%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch
rename to packages/SystemUI/tests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
index c2c94a8..1cabf20 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
@@ -77,6 +77,8 @@
                 INITIATION_WIDTH,
                 mKosmos.getCommunalInteractor(),
                 mKosmos.getConfigurationInteractor(),
+                mKosmos.getSceneInteractor(),
+                Optional.of(mKosmos.getMockWindowRootViewProvider()),
                 mLifecycle
                 );
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
index d7fcb6a..74e8257 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorParameterizedTest.kt
@@ -357,7 +357,10 @@
     fun dataUpdatedOnIncrementSignalCountAfterInitialDelay() =
         testScope.runTest {
             setUpForDeviceConnection()
-            tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, eduClock.instant())
+            tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+                DeviceType.TOUCHPAD,
+                eduClock.instant(),
+            )
 
             val model by collectLastValue(repository.readGestureEduModelFlow(gestureType))
             val originalValue = model!!.signalCount
@@ -372,7 +375,10 @@
     fun dataUnchangedOnIncrementSignalCountBeforeInitialDelay() =
         testScope.runTest {
             setUpForDeviceConnection()
-            tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, eduClock.instant())
+            tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+                DeviceType.TOUCHPAD,
+                eduClock.instant(),
+            )
 
             val model by collectLastValue(repository.readGestureEduModelFlow(gestureType))
             val originalValue = model!!.signalCount
@@ -398,8 +404,14 @@
         }
 
     private suspend fun setUpForInitialDelayElapse() {
-        tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, eduClock.instant())
-        tutorialSchedulerRepository.updateLaunchTime(DeviceType.KEYBOARD, eduClock.instant())
+        tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+            DeviceType.TOUCHPAD,
+            eduClock.instant(),
+        )
+        tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+            DeviceType.KEYBOARD,
+            eduClock.instant(),
+        )
         eduClock.offset(initialDelayElapsedDuration)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index 580f631..692b9c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -151,8 +151,14 @@
         }
 
     private suspend fun setUpForInitialDelayElapse() {
-        tutorialSchedulerRepository.updateLaunchTime(DeviceType.TOUCHPAD, eduClock.instant())
-        tutorialSchedulerRepository.updateLaunchTime(DeviceType.KEYBOARD, eduClock.instant())
+        tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+            DeviceType.TOUCHPAD,
+            eduClock.instant(),
+        )
+        tutorialSchedulerRepository.setScheduledTutorialLaunchTime(
+            DeviceType.KEYBOARD,
+            eduClock.instant(),
+        )
         eduClock.offset(initialDelayElapsedDuration)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
index 67e03e4..82bf5e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.SystemUIAppComponentFactoryBase
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.DialogTransitionAnimator
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.dock.DockManagerFake
 import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
@@ -133,6 +134,7 @@
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         val remoteUserSelectionManager =
@@ -203,6 +205,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 sceneInteractor = { kosmos.sceneInteractor },
             )
         underTest.previewManager =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
index 32fa160..111d819 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorParameterizedTest.kt
@@ -20,7 +20,6 @@
 import android.app.admin.DevicePolicyManager
 import android.content.Intent
 import android.os.UserHandle
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.SmallTest
 import com.android.internal.widget.LockPatternUtils
 import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
@@ -30,6 +29,7 @@
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.dock.DockManagerFake
 import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.flags.FakeFeatureFlags
@@ -64,6 +64,7 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyInt
@@ -82,7 +83,7 @@
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4::class)
 @DisableSceneContainer
-@FlakyTest(bugId = 292574995, detail = "NullPointer on MockMakerTypeMockability.mockable()")
+@Ignore("b/292574995 NullPointer on MockMakerTypeMockability.mockable()")
 class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
 
     companion object {
@@ -270,6 +271,7 @@
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         val remoteUserSelectionManager =
@@ -320,6 +322,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 sceneInteractor = { kosmos.sceneInteractor },
             )
     }
@@ -344,7 +347,7 @@
                         canShowWhileLocked = canShowWhileLocked,
                     )
                 } else {
-                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
 
             underTest.onQuickAffordanceTriggered(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
index 1184a76..8c00047 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorSceneContainerTest.kt
@@ -30,6 +30,7 @@
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.ContentDescription
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.dock.DockManagerFake
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.FakeFeatureFlags
@@ -81,7 +82,7 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @FlakyTest(
     bugId = 292574995,
-    detail = "on certain architectures all permutations with startActivity=true is causing failures"
+    detail = "on certain architectures all permutations with startActivity=true is causing failures",
 )
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4::class)
@@ -93,11 +94,7 @@
         private val DRAWABLE =
             mock<Icon> {
                 whenever(this.contentDescription)
-                    .thenReturn(
-                        ContentDescription.Resource(
-                            res = CONTENT_DESCRIPTION_RESOURCE_ID,
-                        )
-                    )
+                    .thenReturn(ContentDescription.Resource(res = CONTENT_DESCRIPTION_RESOURCE_ID))
             }
         private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337
 
@@ -273,16 +270,11 @@
                 context = context,
                 userFileManager =
                     mock<UserFileManager>().apply {
-                        whenever(
-                                getSharedPreferences(
-                                    anyString(),
-                                    anyInt(),
-                                    anyInt(),
-                                )
-                            )
+                        whenever(getSharedPreferences(anyString(), anyInt(), anyInt()))
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         val remoteUserSelectionManager =
@@ -316,9 +308,7 @@
         underTest =
             KeyguardQuickAffordanceInteractor(
                 keyguardInteractor =
-                    KeyguardInteractorFactory.create(
-                            featureFlags = featureFlags,
-                        )
+                    KeyguardInteractorFactory.create(featureFlags = featureFlags)
                         .keyguardInteractor,
                 shadeInteractor = kosmos.shadeInteractor,
                 lockPatternUtils = lockPatternUtils,
@@ -335,6 +325,7 @@
                 biometricSettingsRepository = biometricSettingsRepository,
                 backgroundDispatcher = testDispatcher,
                 appContext = mContext,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 sceneInteractor = { kosmos.sceneInteractor },
             )
     }
@@ -350,9 +341,7 @@
 
             homeControls.setState(
                 lockScreenState =
-                    KeyguardQuickAffordanceConfig.LockScreenState.Visible(
-                        icon = DRAWABLE,
-                    )
+                    KeyguardQuickAffordanceConfig.LockScreenState.Visible(icon = DRAWABLE)
             )
             homeControls.onTriggeredResult =
                 if (startActivity) {
@@ -361,7 +350,7 @@
                         canShowWhileLocked = canShowWhileLocked,
                     )
                 } else {
-                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
+                    KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled(false)
                 }
 
             underTest.onQuickAffordanceTriggered(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
index 3364528..0b2b867 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt
@@ -29,10 +29,11 @@
 import com.android.systemui.animation.DialogTransitionAnimator
 import com.android.systemui.animation.Expandable
 import com.android.systemui.common.shared.model.Icon
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.dock.DockManagerFake
-import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.quickaffordance.BuiltInKeyguardQuickAffordanceKeys
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
 import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceProviderClientFactory
@@ -190,10 +191,7 @@
         dockManager = DockManagerFake()
         biometricSettingsRepository = FakeBiometricSettingsRepository()
 
-        val featureFlags =
-            FakeFeatureFlags().apply { set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false) }
-
-        val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
+        val withDeps = KeyguardInteractorFactory.create()
         keyguardInteractor = withDeps.keyguardInteractor
         repository = withDeps.repository
 
@@ -216,6 +214,7 @@
                             .thenReturn(FakeSharedPreferences())
                     },
                 userTracker = userTracker,
+                communalSettingsInteractor = kosmos.communalSettingsInteractor,
                 broadcastDispatcher = fakeBroadcastDispatcher,
             )
         val remoteUserSelectionManager =
@@ -285,7 +284,7 @@
                         keyguardStateController = keyguardStateController,
                         userTracker = userTracker,
                         activityStarter = activityStarter,
-                        featureFlags = featureFlags,
+                        featureFlags = kosmos.fakeFeatureFlagsClassic,
                         repository = { quickAffordanceRepository },
                         launchAnimator = launchAnimator,
                         logger = logger,
@@ -295,6 +294,7 @@
                         biometricSettingsRepository = biometricSettingsRepository,
                         backgroundDispatcher = kosmos.testDispatcher,
                         appContext = mContext,
+                        communalSettingsInteractor = kosmos.communalSettingsInteractor,
                         sceneInteractor = { kosmos.sceneInteractor },
                     ),
                 keyguardInteractor = keyguardInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 47371df..23282b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -20,6 +20,7 @@
 
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -27,6 +28,8 @@
 
 import android.app.KeyguardManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.media.AudioManager;
 import android.media.session.MediaController;
@@ -38,6 +41,7 @@
 import android.view.View;
 import android.widget.Button;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import androidx.core.graphics.drawable.IconCompat;
@@ -128,6 +132,21 @@
         when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE);
         mMediaControllers.add(mMediaController);
         when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers);
+        createMediaSwitchingController(TEST_PACKAGE);
+
+        // Using a fake package will cause routing operations to fail, so we intercept
+        // scanning-related operations.
+        mMediaSwitchingController.mLocalMediaManager = mock(LocalMediaManager.class);
+        doNothing().when(mMediaSwitchingController.mLocalMediaManager).startScan();
+        doNothing().when(mMediaSwitchingController.mLocalMediaManager).stopScan();
+
+        mMediaOutputBaseDialogImpl =
+                new MediaOutputBaseDialogImpl(
+                        mContext, mBroadcastSender, mMediaSwitchingController);
+        mMediaOutputBaseDialogImpl.onCreate(new Bundle());
+    }
+
+    private void createMediaSwitchingController(String testPackage) {
         VolumePanelGlobalStateInteractor volumePanelGlobalStateInteractor =
                 VolumePanelGlobalStateInteractorKosmosKt.getVolumePanelGlobalStateInteractor(
                         mKosmos);
@@ -135,7 +154,7 @@
         mMediaSwitchingController =
                 new MediaSwitchingController(
                         mContext,
-                        TEST_PACKAGE,
+                        testPackage,
                         mContext.getUser(),
                         /* token */ null,
                         mMediaSessionManager,
@@ -150,17 +169,40 @@
                         mFlags,
                         volumePanelGlobalStateInteractor,
                         mUserTracker);
+    }
 
-        // Using a fake package will cause routing operations to fail, so we intercept
-        // scanning-related operations.
-        mMediaSwitchingController.mLocalMediaManager = mock(LocalMediaManager.class);
-        doNothing().when(mMediaSwitchingController.mLocalMediaManager).startScan();
-        doNothing().when(mMediaSwitchingController.mLocalMediaManager).stopScan();
+    @Test
+    public void onCreate_noAppOpenIntent_metadataSectionNonClickable() {
+        createMediaSwitchingController(null);
 
         mMediaOutputBaseDialogImpl =
                 new MediaOutputBaseDialogImpl(
                         mContext, mBroadcastSender, mMediaSwitchingController);
         mMediaOutputBaseDialogImpl.onCreate(new Bundle());
+        final LinearLayout mediaMetadataSectionLayout =
+                mMediaOutputBaseDialogImpl.mDialogView.requireViewById(
+                        R.id.media_metadata_section);
+
+        assertThat(mediaMetadataSectionLayout.isClickable()).isFalse();
+    }
+
+    @Test
+    public void onCreate_appOpenIntentAvailable_metadataSectionClickable() {
+        final PackageManager packageManager = mock(PackageManager.class);
+        mContext.setMockPackageManager(packageManager);
+        Intent intent = new Intent(TEST_PACKAGE);
+        doReturn(intent).when(packageManager).getLaunchIntentForPackage(TEST_PACKAGE);
+        createMediaSwitchingController(TEST_PACKAGE);
+
+        mMediaOutputBaseDialogImpl =
+                new MediaOutputBaseDialogImpl(
+                        mContext, mBroadcastSender, mMediaSwitchingController);
+        mMediaOutputBaseDialogImpl.onCreate(new Bundle());
+        final LinearLayout mediaMetadataSectionLayout =
+                mMediaOutputBaseDialogImpl.mDialogView.requireViewById(
+                        R.id.media_metadata_section);
+
+        assertThat(mediaMetadataSectionLayout.isClickable()).isTrue();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
index b26f0a6..782b248 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
@@ -557,6 +557,13 @@
     }
 
     @Test
+    public void startActivityForDialog_always_startActivityWithoutDismissShade() {
+        mInternetDialogController.startActivityForDialog(mock(Intent.class));
+
+        verify(mActivityStarter).startActivity(any(Intent.class), eq(false) /* dismissShade */);
+    }
+
+    @Test
     public void launchWifiDetailsSetting_withNoWifiEntryKey_doNothing() {
         mInternetDialogController.launchWifiDetailsSetting(null /* key */, mDialogLaunchView);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
index 300c9b8..8560b67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
@@ -35,6 +35,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.DialogTransitionAnimator;
 import com.android.systemui.res.R;
+import com.android.systemui.shade.domain.interactor.FakeShadeDialogContextInteractor;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -149,7 +150,8 @@
                 mHandler,
                 mBgExecutor,
                 mKeyguard,
-                mSystemUIDialogFactory);
+                mSystemUIDialogFactory,
+                new FakeShadeDialogContextInteractor(mContext));
         mInternetDialogDelegate.createDialog();
         mInternetDialogDelegate.onCreate(mSystemUIDialog, null);
         mInternetDialogDelegate.mAdapter = mInternetAdapter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
index afff485..a17f100 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
@@ -36,6 +36,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.media.projection.StopReason;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -154,7 +155,7 @@
         PendingIntent stopIntent = Mockito.mock(PendingIntent.class);
 
         mController.startCountdown(0, 0, startIntent, stopIntent);
-        mController.stopRecording();
+        mController.stopRecording(StopReason.STOP_UNKNOWN);
 
         assertFalse(mController.isStarting());
         assertFalse(mController.isRecording());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
index 9fb752a..4471c58 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/DisplayTrackerImplTest.kt
@@ -17,7 +17,7 @@
 package com.android.systemui.settings
 
 import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS
+import android.hardware.display.DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS
 import android.hardware.display.DisplayManagerGlobal
 import android.os.Handler
 import android.testing.AndroidTestingRunner
@@ -98,7 +98,7 @@
                 any(),
                 any(),
                 eq(0L),
-                eq(PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS),
+                eq(PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS),
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index c410111..6724f82 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -699,6 +699,30 @@
             }
         }
 
+    @Test
+    fun onTouchEvent_qsExpanding_touchesNotDispatched() =
+        with(kosmos) {
+            testScope.runTest {
+                // On lockscreen.
+                goToScene(CommunalScenes.Blank)
+                whenever(
+                        notificationStackScrollLayoutController.isBelowLastNotification(
+                            any(),
+                            any(),
+                        )
+                    )
+                    .thenReturn(true)
+
+                // Shade is open slightly.
+                shadeTestUtil.setQsExpansion(0.01f)
+                testableLooper.processAllMessages()
+
+                // Touches are not consumed.
+                assertThat(underTest.onTouchEvent(DOWN_EVENT)).isFalse()
+                verify(containerView, never()).onTouchEvent(DOWN_EVENT)
+            }
+        }
+
     @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
     @Test
     fun onTouchEvent_bouncerInteracting_movesNotDispatched() =
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 041d1a6..e68153a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -17,12 +17,12 @@
 package com.android.systemui.shade
 
 import android.content.Context
-import android.platform.test.annotations.DisableFlags
 import android.platform.test.annotations.EnableFlags
 import android.platform.test.annotations.RequiresFlagsDisabled
 import android.platform.test.flag.junit.FlagsParameterization
 import android.testing.TestableLooper
 import android.testing.TestableLooper.RunWithLooper
+import android.view.Choreographer
 import android.view.KeyEvent
 import android.view.MotionEvent
 import android.view.View
@@ -32,7 +32,6 @@
 import com.android.keyguard.KeyguardSecurityContainerController
 import com.android.keyguard.dagger.KeyguardBouncerComponent
 import com.android.systemui.Flags
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
@@ -59,6 +58,7 @@
 import com.android.systemui.settings.brightness.domain.interactor.BrightnessMirrorShowingInteractor
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
+import com.android.systemui.statusbar.BlurUtils
 import com.android.systemui.statusbar.DragDownHelper
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
 import com.android.systemui.statusbar.NotificationInsetsController
@@ -82,6 +82,7 @@
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.window.ui.viewmodel.WindowRootViewModel
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
 import kotlinx.coroutines.Dispatchers
@@ -157,6 +158,9 @@
     @Mock lateinit var sysUIKeyEventHandler: SysUIKeyEventHandler
     @Mock lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
     @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    @Mock private lateinit var blurUtils: BlurUtils
+    @Mock private lateinit var choreographer: Choreographer
+    @Mock private lateinit var windowViewModelFactory: WindowRootViewModel.Factory
     private val notificationLaunchAnimationRepository = NotificationLaunchAnimationRepository()
     private val notificationLaunchAnimationInteractor =
         NotificationLaunchAnimationInteractor(notificationLaunchAnimationRepository)
@@ -205,6 +209,9 @@
         fakeClock = FakeSystemClock()
         underTest =
             NotificationShadeWindowViewController(
+                blurUtils,
+                windowViewModelFactory,
+                choreographer,
                 lockscreenShadeTransitionController,
                 falsingCollector,
                 sysuiStatusBarStateController,
@@ -406,18 +413,6 @@
         }
 
     @Test
-    @DisableSceneContainer
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun handleDispatchTouchEvent_nsslMigrationOff_userActivity_not_called() {
-        underTest.setStatusBarViewController(phoneStatusBarViewController)
-
-        interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
-
-        verify(centralSurfaces, times(0)).userActivity()
-    }
-
-    @Test
-    @EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun handleDispatchTouchEvent_nsslMigrationOn_userActivity() {
         underTest.setStatusBarViewController(phoneStatusBarViewController)
 
@@ -438,7 +433,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun shouldInterceptTouchEvent_dozing_touchNotInLockIconArea_touchIntercepted() {
         // GIVEN dozing
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
@@ -451,7 +445,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun shouldInterceptTouchEvent_dozing_touchInStatusBar_touchIntercepted() {
         // GIVEN dozing
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
@@ -464,7 +457,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun shouldInterceptTouchEvent_dozingAndPulsing_touchIntercepted() {
         // GIVEN dozing
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
@@ -609,7 +601,6 @@
     }
 
     @Test
-    @EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
     fun cancelCurrentTouch_callsDragDownHelper() {
         underTest.cancelCurrentTouch()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
index 13bc82f..a04ca03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerLegacyTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.shade
 
-import android.platform.test.annotations.DisableFlags
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
@@ -27,7 +26,6 @@
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.fragments.FragmentHostManager
 import com.android.systemui.fragments.FragmentService
@@ -65,10 +63,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
-/**
- * Uses Flags.KEYGUARD_STATUS_VIEW_MIGRATE_NSSL set to false. If all goes well, this set of tests
- * will be deleted.
- */
+/** NotificationsQSContainerController tests */
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
@@ -122,7 +117,7 @@
                 delayableExecutor,
                 notificationStackScrollLayoutController,
                 ResourcesSplitShadeStateController(),
-                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
+                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
             )
 
         overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN)
@@ -209,23 +204,23 @@
         given(
             taskbarVisible = true,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0, // taskbar should disappear when shade is expanded
             expectedNotificationsMargin = NOTIFICATIONS_MARGIN,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = true,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = STABLE_INSET_BOTTOM,
             expectedNotificationsMargin = NOTIFICATIONS_MARGIN,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -237,22 +232,22 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0, // qs goes full height as it's not obscuring nav buttons
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -263,22 +258,22 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withCutout()
+            insets = windowInsets().withCutout(),
         )
         then(
             expectedContainerPadding = CUTOUT_HEIGHT,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withCutout().withStableBottom()
+            insets = windowInsets().withCutout().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -289,18 +284,18 @@
         given(
             taskbarVisible = true,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM)
 
         given(
             taskbarVisible = true,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = STABLE_INSET_BOTTOM,
-            expectedQsPadding = STABLE_INSET_BOTTOM
+            expectedQsPadding = STABLE_INSET_BOTTOM,
         )
     }
 
@@ -314,19 +309,19 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withCutout().withStableBottom()
+            insets = windowInsets().withCutout().withStableBottom(),
         )
         then(expectedContainerPadding = CUTOUT_HEIGHT, expectedQsPadding = STABLE_INSET_BOTTOM)
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM
+            expectedQsPadding = STABLE_INSET_BOTTOM,
         )
     }
 
@@ -339,7 +334,7 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0, expectedNotificationsMargin = 0)
 
@@ -355,7 +350,7 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0)
 
@@ -376,43 +371,6 @@
     }
 
     @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testSplitShadeLayout_isAlignedToGuideline() {
-        enableSplitShade()
-        underTest.updateResources()
-        assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd).isEqualTo(R.id.qs_edge_guideline)
-        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
-            .isEqualTo(R.id.qs_edge_guideline)
-    }
-
-    @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testSinglePaneLayout_childrenHaveEqualMargins() {
-        disableSplitShade()
-        underTest.updateResources()
-        val qsStartMargin = getConstraintSetLayout(R.id.qs_frame).startMargin
-        val qsEndMargin = getConstraintSetLayout(R.id.qs_frame).endMargin
-        val notifStartMargin = getConstraintSetLayout(R.id.notification_stack_scroller).startMargin
-        val notifEndMargin = getConstraintSetLayout(R.id.notification_stack_scroller).endMargin
-        assertThat(
-                qsStartMargin == qsEndMargin &&
-                    notifStartMargin == notifEndMargin &&
-                    qsStartMargin == notifStartMargin
-            )
-            .isTrue()
-    }
-
-    @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testSplitShadeLayout_childrenHaveInsideMarginsOfZero() {
-        enableSplitShade()
-        underTest.updateResources()
-        assertThat(getConstraintSetLayout(R.id.qs_frame).endMargin).isEqualTo(0)
-        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startMargin)
-            .isEqualTo(0)
-    }
-
-    @Test
     fun testSplitShadeLayout_qsFrameHasHorizontalMarginsOfZero() {
         enableSplitShade()
         underTest.updateResources()
@@ -421,37 +379,6 @@
     }
 
     @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testLargeScreenLayout_qsAndNotifsTopMarginIsOfHeaderHeightHelper() {
-        setLargeScreen()
-        val largeScreenHeaderResourceHeight = 100
-        val largeScreenHeaderHelperHeight = 200
-        whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
-            .thenReturn(largeScreenHeaderHelperHeight)
-        overrideResource(R.dimen.large_screen_shade_header_height, largeScreenHeaderResourceHeight)
-
-        // ensure the estimated height (would be 30 here) wouldn't impact this test case
-        overrideResource(R.dimen.large_screen_shade_header_min_height, 10)
-        overrideResource(R.dimen.new_qs_header_non_clickable_element_height, 10)
-
-        underTest.updateResources()
-
-        assertThat(getConstraintSetLayout(R.id.qs_frame).topMargin)
-            .isEqualTo(largeScreenHeaderHelperHeight)
-        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).topMargin)
-            .isEqualTo(largeScreenHeaderHelperHeight)
-    }
-
-    @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testSmallScreenLayout_qsAndNotifsTopMarginIsZero() {
-        setSmallScreen()
-        underTest.updateResources()
-        assertThat(getConstraintSetLayout(R.id.qs_frame).topMargin).isEqualTo(0)
-        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).topMargin).isEqualTo(0)
-    }
-
-    @Test
     fun testSinglePaneShadeLayout_qsFrameHasHorizontalMarginsSetToCorrectValue() {
         disableSplitShade()
         underTest.updateResources()
@@ -464,17 +391,6 @@
     }
 
     @Test
-    @DisableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
-    fun testSinglePaneShadeLayout_isAlignedToParent() {
-        disableSplitShade()
-        underTest.updateResources()
-        assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd)
-            .isEqualTo(ConstraintSet.PARENT_ID)
-        assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
-            .isEqualTo(ConstraintSet.PARENT_ID)
-    }
-
-    @Test
     fun testAllChildrenOfNotificationContainer_haveIds() {
         // set dimen to 0 to avoid triggering updating bottom spacing
         overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, 0)
@@ -493,7 +409,7 @@
                 delayableExecutor,
                 notificationStackScrollLayoutController,
                 ResourcesSplitShadeStateController(),
-                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
+                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
             )
         controller.updateConstraints()
 
@@ -509,7 +425,7 @@
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
             insets = emptyInsets(),
-            applyImmediately = false
+            applyImmediately = false,
         )
         fakeSystemClock.advanceTime(INSET_DEBOUNCE_MILLIS / 2)
         windowInsetsCallback.accept(windowInsets().withStableBottom())
@@ -576,7 +492,7 @@
         taskbarVisible: Boolean,
         navigationMode: Int,
         insets: WindowInsets,
-        applyImmediately: Boolean = true
+        applyImmediately: Boolean = true,
     ) {
         Mockito.clearInvocations(view)
         taskbarVisibilityCallback.onTaskbarStatusUpdated(taskbarVisible, false)
@@ -591,7 +507,7 @@
     fun then(
         expectedContainerPadding: Int,
         expectedNotificationsMargin: Int = NOTIFICATIONS_MARGIN,
-        expectedQsPadding: Int = 0
+        expectedQsPadding: Int = 0,
     ) {
         verify(view).setPadding(anyInt(), anyInt(), anyInt(), eq(expectedContainerPadding))
         verify(view).setNotificationsMarginBottom(expectedNotificationsMargin)
@@ -623,7 +539,7 @@
         val layoutParams =
             ConstraintLayout.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT
+                ViewGroup.LayoutParams.WRAP_CONTENT,
             )
         // required as cloning ConstraintSet fails if view doesn't have layout params
         view.layoutParams = layoutParams
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
index 4850b0f..24f8843 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationsQSContainerControllerTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.shade
 
-import android.platform.test.annotations.EnableFlags
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.View
@@ -27,7 +26,6 @@
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.test.filters.SmallTest
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.fragments.FragmentHostManager
 import com.android.systemui.fragments.FragmentService
@@ -68,7 +66,6 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
-@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
 class NotificationsQSContainerControllerTest : SysuiTestCase() {
 
     private val view = mock<NotificationsQuickSettingsContainer>()
@@ -120,7 +117,7 @@
                 delayableExecutor,
                 notificationStackScrollLayoutController,
                 ResourcesSplitShadeStateController(),
-                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
+                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
             )
 
         overrideResource(R.dimen.split_shade_notifications_scrim_margin_bottom, SCRIM_MARGIN)
@@ -205,23 +202,23 @@
         given(
             taskbarVisible = true,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0, // taskbar should disappear when shade is expanded
             expectedNotificationsMargin = NOTIFICATIONS_MARGIN,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = true,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = STABLE_INSET_BOTTOM,
             expectedNotificationsMargin = NOTIFICATIONS_MARGIN,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -233,22 +230,22 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0, // qs goes full height as it's not obscuring nav buttons
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -259,22 +256,22 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withCutout()
+            insets = windowInsets().withCutout(),
         )
         then(
             expectedContainerPadding = CUTOUT_HEIGHT,
-            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withCutout().withStableBottom()
+            insets = windowInsets().withCutout().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET
+            expectedQsPadding = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN - QS_PADDING_OFFSET,
         )
     }
 
@@ -285,18 +282,18 @@
         given(
             taskbarVisible = true,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0, expectedQsPadding = STABLE_INSET_BOTTOM)
 
         given(
             taskbarVisible = true,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = STABLE_INSET_BOTTOM,
-            expectedQsPadding = STABLE_INSET_BOTTOM
+            expectedQsPadding = STABLE_INSET_BOTTOM,
         )
     }
 
@@ -310,19 +307,19 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withCutout().withStableBottom()
+            insets = windowInsets().withCutout().withStableBottom(),
         )
         then(expectedContainerPadding = CUTOUT_HEIGHT, expectedQsPadding = STABLE_INSET_BOTTOM)
 
         given(
             taskbarVisible = false,
             navigationMode = BUTTONS_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(
             expectedContainerPadding = 0,
             expectedNotificationsMargin = STABLE_INSET_BOTTOM + NOTIFICATIONS_MARGIN,
-            expectedQsPadding = STABLE_INSET_BOTTOM
+            expectedQsPadding = STABLE_INSET_BOTTOM,
         )
     }
 
@@ -335,7 +332,7 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0, expectedNotificationsMargin = 0)
 
@@ -351,7 +348,7 @@
         given(
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
-            insets = windowInsets().withStableBottom()
+            insets = windowInsets().withStableBottom(),
         )
         then(expectedContainerPadding = 0)
 
@@ -467,7 +464,7 @@
                 delayableExecutor,
                 notificationStackScrollLayoutController,
                 ResourcesSplitShadeStateController(),
-                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
+                largeScreenHeaderHelperLazy = { largeScreenHeaderHelper },
             )
         controller.updateConstraints()
 
@@ -483,7 +480,7 @@
             taskbarVisible = false,
             navigationMode = GESTURES_NAVIGATION,
             insets = emptyInsets(),
-            applyImmediately = false
+            applyImmediately = false,
         )
         fakeSystemClock.advanceTime(INSET_DEBOUNCE_MILLIS / 2)
         windowInsetsCallback.accept(windowInsets().withStableBottom())
@@ -550,7 +547,7 @@
         taskbarVisible: Boolean,
         navigationMode: Int,
         insets: WindowInsets,
-        applyImmediately: Boolean = true
+        applyImmediately: Boolean = true,
     ) {
         Mockito.clearInvocations(view)
         taskbarVisibilityCallback.onTaskbarStatusUpdated(taskbarVisible, false)
@@ -565,7 +562,7 @@
     fun then(
         expectedContainerPadding: Int,
         expectedNotificationsMargin: Int = NOTIFICATIONS_MARGIN,
-        expectedQsPadding: Int = 0
+        expectedQsPadding: Int = 0,
     ) {
         verify(view).setPadding(anyInt(), anyInt(), anyInt(), eq(expectedContainerPadding))
         verify(view).setNotificationsMarginBottom(expectedNotificationsMargin)
@@ -597,7 +594,7 @@
         val layoutParams =
             ConstraintLayout.LayoutParams(
                 ViewGroup.LayoutParams.WRAP_CONTENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT
+                ViewGroup.LayoutParams.WRAP_CONTENT,
             )
         // required as cloning ConstraintSet fails if view doesn't have layout params
         view.layoutParams = layoutParams
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 3a46d03..cfc00a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -364,79 +364,6 @@
         }
 
     @Test
-    fun setDragAmount_setsKeyguardTransitionProgress() =
-        testScope.runTest {
-            transitionController.dragDownAmount = 10f
-
-            verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), anyInt())
-        }
-
-    @Test
-    fun setDragAmount_setsKeyguardAlphaBasedOnDistance() =
-        testScope.runTest {
-            val alphaDistance =
-                context.resources.getDimensionPixelSize(
-                    R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
-                )
-            transitionController.dragDownAmount = 10f
-
-            val expectedAlpha = 1 - 10f / alphaDistance
-            verify(shadeLockscreenInteractor)
-                .setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
-        }
-
-    @Test
-    fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() =
-        testScope.runTest {
-            val mediaTranslationY = 123
-            disableSplitShade()
-            whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
-            whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
-                .thenReturn(mediaTranslationY)
-
-            transitionController.dragDownAmount = 10f
-
-            verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), eq(0))
-        }
-
-    @Test
-    fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() =
-        testScope.runTest {
-            val mediaTranslationY = 123
-            enableSplitShade()
-            whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
-            whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
-                .thenReturn(mediaTranslationY)
-
-            transitionController.dragDownAmount = 10f
-
-            verify(shadeLockscreenInteractor)
-                .setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
-        }
-
-    @Test
-    fun setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistance() =
-        testScope.runTest {
-            enableSplitShade()
-            whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(false)
-            whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()).thenReturn(123)
-
-            transitionController.dragDownAmount = 10f
-
-            val distance =
-                context.resources.getDimensionPixelSize(
-                    R.dimen.lockscreen_shade_keyguard_transition_distance
-                )
-            val offset =
-                context.resources.getDimensionPixelSize(
-                    R.dimen.lockscreen_shade_keyguard_transition_vertical_offset
-                )
-            val expectedTranslation = 10f / distance * offset
-            verify(shadeLockscreenInteractor)
-                .setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
-        }
-
-    @Test
     fun setDragDownAmount_setsValueOnMediaHierarchyManager() =
         testScope.runTest {
             transitionController.dragDownAmount = 10f
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
index 503fa78..1eb88c5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewBinderTest.kt
@@ -89,6 +89,7 @@
                 messagingStyle = null,
                 builder = notificationBuilder,
                 systemUiContext = context,
+                redactText = false,
             )
 
         // WHEN: binds the viewHolder
@@ -149,6 +150,7 @@
                 messagingStyle = style,
                 builder = notificationBuilder,
                 systemUiContext = context,
+                redactText = false,
             )
         // WHEN: binds the view
         SingleLineViewBinder.bind(viewModel, view)
@@ -197,6 +199,7 @@
                 messagingStyle = null,
                 builder = notificationBuilder,
                 systemUiContext = context,
+                redactText = false,
             )
         // WHEN: binds the view with the view model
         SingleLineViewBinder.bind(viewModel, view)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
index d366632..ef70e27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflaterTest.kt
@@ -379,7 +379,8 @@
             this,
             if (isConversation) messagingStyle else null,
             builder,
-            context
+            context,
+            false
         )
     }
 
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 a91fb45..e1a8916 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
@@ -1544,14 +1544,6 @@
         assertFalse(mStackScroller.mHeadsUpAnimatingAway);
     }
 
-    @Test
-    @EnableSceneContainer
-    public void finishExpanding_sceneContainerEnabled() {
-        mStackScroller.startOverscrollAfterExpanding();
-        verify(mStackScroller.getExpandHelper()).finishExpanding();
-        assertTrue(mStackScroller.getIsBeingDragged());
-    }
-
     private MotionEvent captureTouchSentToSceneFramework() {
         ArgumentCaptor<MotionEvent> captor = ArgumentCaptor.forClass(MotionEvent.class);
         verify(mStackScrollLayoutController).sendTouchToSceneFramework(captor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index d157cf2d..411c81d13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -69,7 +69,6 @@
 import android.hardware.devicestate.DeviceState;
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.display.AmbientDisplayConfiguration;
-import android.hardware.fingerprint.FingerprintManager;
 import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.Handler;
@@ -123,7 +122,6 @@
 import com.android.systemui.flags.DisableSceneContainer;
 import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -360,7 +358,6 @@
     @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
     @Mock private UserTracker mUserTracker;
     @Mock private AvalancheProvider mAvalancheProvider;
-    @Mock private FingerprintManager mFingerprintManager;
     @Mock IPowerManager mPowerManagerService;
     @Mock ActivityStarter mActivityStarter;
     @Mock private WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor;
@@ -399,8 +396,6 @@
 
         // Set default value to avoid IllegalStateException.
         mFeatureFlags.set(SHORTCUT_LIST_SEARCH_LAYOUT, false);
-        // Turn AOD on and toggle feature flag for jank fixes
-        mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
         when(mDozeParameters.getAlwaysOn()).thenReturn(true);
 
         IThermalService thermalService = mock(IThermalService.class);
@@ -443,7 +438,6 @@
         mVisualInterruptionDecisionProvider.start();
 
         mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
-        mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
 
         mMetricsLogger = new FakeMetricsLogger();
 
@@ -637,7 +631,6 @@
                 mLightRevealScrim,
                 mAlternateBouncerInteractor,
                 mUserTracker,
-                () -> mFingerprintManager,
                 mActivityStarter,
                 mBrightnessMirrorShowingInteractor,
                 mGlanceableHubContainerController,
@@ -1121,27 +1114,6 @@
         verify(mStatusBarStateController).setState(SHADE);
     }
 
-    /** Regression test for b/298355063 */
-    @Test
-    public void fingerprintManagerNull_noNPE() {
-        // GIVEN null fingerprint manager
-        mFingerprintManager = null;
-        createCentralSurfaces();
-
-        // GIVEN should animate doze wakeup
-        when(mDozeServiceHost.shouldAnimateWakeup()).thenReturn(true);
-        when(mBiometricUnlockController.getMode()).thenReturn(
-                BiometricUnlockController.MODE_ONLY_WAKE);
-        when(mDozeServiceHost.isPulsing()).thenReturn(false);
-        when(mStatusBarStateController.getDozeAmount()).thenReturn(1f);
-
-        // WHEN waking up from the power button
-        mWakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
-        mCentralSurfaces.mWakefulnessObserver.onStartedWakingUp();
-
-        // THEN no NPE when fingerprintManager is null
-    }
-
     @Test
     @DisableFlags(StatusBarConnectedDisplays.FLAG_NAME)
     public void bubbleBarVisibility() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index eb1e28b..b17a58f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -49,11 +49,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
-    private static final int SCREEN_HEIGHT = 2000;
-    private static final int EMPTY_HEIGHT = 0;
     private static final float ZERO_DRAG = 0.f;
-    private static final float OPAQUE = 1.f;
-    private static final float TRANSPARENT = 0.f;
 
     @Mock private Resources mResources;
 
@@ -62,19 +58,10 @@
 
     private MockitoSession mStaticMockSession;
 
-    private float mPanelExpansion;
-    private int mKeyguardStatusBarHeaderHeight;
-    private int mKeyguardStatusHeight;
-    private int mUserSwitchHeight;
     private float mDark;
-    private float mQsExpansion;
-    private int mCutoutTopInset = 0;
     private boolean mIsSplitShade = false;
     private boolean mBypassEnabled = false;
     private int mUnlockedStackScrollerPadding = 0;
-    private float mUdfpsTop = -1;
-    private float mClockBottom = SCREEN_HEIGHT / 2;
-    private boolean mClockTopAligned;
 
     @Before
     public void setUp() {
@@ -99,118 +86,9 @@
     }
 
     @Test
-    public void clockPositionTopOfScreenOnAOD() {
-        // GIVEN on AOD and clock has 0 height
-        givenAOD();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position is the top of the screen
-        assertThat(mClockPosition.clockY).isEqualTo(0);
-        // AND the clock is opaque and positioned on the left.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
-    }
-
-    @Test
-    public void clockPositionBelowCutout() {
-        // GIVEN on AOD and clock has 0 height
-        givenAOD();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        mCutoutTopInset = 300;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position is below the cutout
-        assertThat(mClockPosition.clockY).isEqualTo(300);
-        // AND the clock is opaque and positioned on the left.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
-    }
-
-    @Test
-    public void clockPositionAdjustsForKeyguardStatusOnAOD() {
-        // GIVEN on AOD with a clock of height 100
-        givenAOD();
-        mKeyguardStatusHeight = 100;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position is at the top
-        assertThat(mClockPosition.clockY).isEqualTo(0);
-        // AND the clock is opaque and positioned on the left.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
-    }
-
-    @Test
-    public void clockPositionLargeClockOnAOD() {
-        // GIVEN on AOD with a full screen clock
-        givenAOD();
-        mKeyguardStatusHeight = SCREEN_HEIGHT;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position doesn't overflow the screen.
-        assertThat(mClockPosition.clockY).isEqualTo(0);
-        // AND the clock is opaque and positioned on the left.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
-    }
-
-    @Test
-    public void clockPositionTopOfScreenOnLockScreen() {
-        // GIVEN on lock screen with clock of 0 height
-        givenLockScreen();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position is the top of the screen
-        assertThat(mClockPosition.clockY).isEqualTo(0);
-        // AND the clock is positioned on the left.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-    }
-
-    @Test
-    public void clockPositionWithPartialDragOnLockScreen() {
-        // GIVEN dragging up on lock screen
-        givenLockScreen();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        mPanelExpansion = 0.5f;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock Y position adjusts with drag gesture.
-        assertThat(mClockPosition.clockY).isLessThan(1000);
-        // AND the clock is positioned on the left and not fully opaque.
-        assertThat(mClockPosition.clockX).isEqualTo(0);
-        assertThat(mClockPosition.clockAlpha).isLessThan(OPAQUE);
-    }
-
-    @Test
-    public void clockPositionWithFullDragOnLockScreen() {
-        // GIVEN the lock screen is dragged up
-        givenLockScreen();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        mPanelExpansion = 0.f;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock is transparent.
-        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
-    }
-
-    @Test
-    public void largeClockOnLockScreenIsTransparent() {
-        // GIVEN on lock screen with a full screen clock
-        givenLockScreen();
-        mKeyguardStatusHeight = SCREEN_HEIGHT;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock is transparent
-        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
-    }
-
-    @Test
     public void notifPositionTopOfScreenOnAOD() {
         // GIVEN on AOD and clock has 0 height
         givenAOD();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
         // WHEN the position algorithm is run
         positionClock();
         // THEN the notif padding is 0 (top of screen)
@@ -218,53 +96,9 @@
     }
 
     @Test
-    public void notifPositionIndependentOfKeyguardStatusHeightOnAOD() {
-        // GIVEN on AOD and clock has a nonzero height
-        givenAOD();
-        mKeyguardStatusHeight = 100;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the notif padding adjusts for keyguard status height
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(100);
-    }
-
-    @Test
-    public void notifPositionWithLargeClockOnAOD() {
-        // GIVEN on AOD and clock has a nonzero height
-        givenAOD();
-        mKeyguardStatusHeight = SCREEN_HEIGHT;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the notif padding is, unfortunately, the entire screen.
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(SCREEN_HEIGHT);
-    }
-
-    @Test
-    public void notifPositionMiddleOfScreenOnLockScreen() {
-        // GIVEN on lock screen and clock has 0 height
-        givenLockScreen();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the notif are placed to the top of the screen
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
-    }
-
-    @Test
-    public void notifPositionAdjustsForClockHeightOnLockScreen() {
-        // GIVEN on lock screen and stack scroller has a nonzero height
-        givenLockScreen();
-        mKeyguardStatusHeight = 200;
-        // WHEN the position algorithm is run
-        positionClock();
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(200);
-    }
-
-    @Test
     public void notifPositionAlignedWithClockInSplitShadeMode() {
         givenLockScreen();
         mIsSplitShade = true;
-        mKeyguardStatusHeight = 200;
         // WHEN the position algorithm is run
         positionClock();
         // THEN the notif padding DOESN'T adjust for keyguard status height.
@@ -285,17 +119,6 @@
     }
 
     @Test
-    public void clockPositionedDependingOnMarginInSplitShade() {
-        setSplitShadeTopMargin(400);
-        givenLockScreen();
-        mIsSplitShade = true;
-        // WHEN the position algorithm is run
-        positionClock();
-
-        assertThat(mClockPosition.clockY).isEqualTo(400);
-    }
-
-    @Test
     public void notifPaddingMakesUpToFullMarginInSplitShade_usesHelper() {
         int keyguardSplitShadeTopMargin = 100;
         int largeScreenHeaderHeightHelper = 50;
@@ -317,285 +140,15 @@
     }
 
     @Test
-    public void notifPaddingAccountsForMultiUserSwitcherInSplitShade() {
-        setSplitShadeTopMargin(100);
-        mUserSwitchHeight = 150;
-        givenLockScreen();
-        mIsSplitShade = true;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the notif padding is split shade top margin + user switch height
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(250);
-    }
-
-    @Test
-    public void clockDoesntAccountForMultiUserSwitcherInSplitShade() {
-        setSplitShadeTopMargin(100);
-        mUserSwitchHeight = 150;
-        givenLockScreen();
-        mIsSplitShade = true;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN clockY = split shade top margin
-        assertThat(mClockPosition.clockY).isEqualTo(100);
-    }
-
-    @Test
-    public void notifPaddingExpandedAlignedWithClockInSplitShadeMode() {
-        givenLockScreen();
-        mIsSplitShade = true;
-        mKeyguardStatusHeight = 200;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the padding DOESN'T adjust for keyguard status height.
-        assertThat(mClockPosition.stackScrollerPaddingExpanded)
-                .isEqualTo(mClockPosition.clockY);
-    }
-
-    @Test
-    public void notifPadding_splitShade() {
-        givenLockScreen();
-        mIsSplitShade = true;
-        mKeyguardStatusHeight = 200;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the padding DOESN'T adjust for keyguard status height.
-        assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 10))
-                .isEqualTo(mKeyguardStatusBarHeaderHeight - 10);
-    }
-
-    @Test
-    public void notifPadding_portraitShade_bypassOff() {
-        givenLockScreen();
-        mIsSplitShade = false;
-        mBypassEnabled = false;
-
-        // mMinTopMargin = 100 = 80 + max(20, 0)
-        mKeyguardStatusBarHeaderHeight = 80;
-        mUserSwitchHeight = 20;
-        when(mResources.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin))
-                .thenReturn(0);
-
-        mKeyguardStatusHeight = 200;
-
-        // WHEN the position algorithm is run
-        positionClock();
-
-        // THEN padding = 300 = mMinTopMargin(100) + mKeyguardStatusHeight(200)
-        assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 50))
-                .isEqualTo(300);
-    }
-
-    @Test
-    public void notifPadding_portraitShade_bypassOn() {
-        givenLockScreen();
-        mIsSplitShade = false;
-        mBypassEnabled = true;
-        mUnlockedStackScrollerPadding = 200;
-
-        // WHEN the position algorithm is run
-        positionClock();
-
-        // THEN padding = 150 = mUnlockedStackScrollerPadding(200) - nsslTop(50)
-        assertThat(mClockPositionAlgorithm.getLockscreenNotifPadding(/* nsslTop= */ 50))
-                .isEqualTo(150);
-    }
-
-    @Test
-    public void notifPositionWithLargeClockOnLockScreen() {
-        // GIVEN on lock screen and clock has a nonzero height
-        givenLockScreen();
-        mKeyguardStatusHeight = SCREEN_HEIGHT;
-        // WHEN the position algorithm is run
-        positionClock();
-        // THEN the notif padding is below keyguard status area
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(SCREEN_HEIGHT);
-    }
-
-    @Test
     public void notifPositionWithFullDragOnLockScreen() {
         // GIVEN the lock screen is dragged up
         givenLockScreen();
-        mKeyguardStatusHeight = EMPTY_HEIGHT;
-        mPanelExpansion = 0.f;
         // WHEN the clock position algorithm is run
         positionClock();
         // THEN the notif padding is zero.
         assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
     }
 
-    @Test
-    public void notifPositionWithLargeClockFullDragOnLockScreen() {
-        // GIVEN the lock screen is dragged up and a full screen clock
-        givenLockScreen();
-        mKeyguardStatusHeight = SCREEN_HEIGHT;
-        mPanelExpansion = 0.f;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        assertThat(mClockPosition.stackScrollerPadding).isEqualTo(
-                (int) (mKeyguardStatusHeight * .667f));
-    }
-
-    @Test
-    public void clockHiddenWhenQsIsExpanded() {
-        // GIVEN on the lock screen with visible notifications
-        givenLockScreen();
-        mQsExpansion = 1;
-        // WHEN the clock position algorithm is run
-        positionClock();
-        // THEN the clock is transparent.
-        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
-    }
-
-    @Test
-    public void clockNotHiddenWhenQsIsExpandedInSplitShade() {
-        // GIVEN on the split lock screen with QS expansion
-        givenLockScreen();
-        mIsSplitShade = true;
-        setSplitShadeTopMargin(100);
-        mQsExpansion = 1;
-
-        // WHEN the clock position algorithm is run
-        positionClock();
-
-        assertThat(mClockPosition.clockAlpha).isEqualTo(1);
-    }
-
-    @Test
-    public void clockPositionMinimizesBurnInMovementToAvoidUdfpsOnAOD() {
-        // GIVEN a center aligned clock
-        mClockTopAligned = false;
-
-        // GIVEN the clock + udfps are 100px apart
-        mClockBottom = SCREEN_HEIGHT - 500;
-        mUdfpsTop = SCREEN_HEIGHT - 400;
-
-        // GIVEN it's AOD and the burn-in y value is 200
-        givenAOD();
-        givenMaxBurnInOffset(200);
-
-        // WHEN the clock position algorithm is run with the highest burn in offset
-        givenHighestBurnInOffset();
-        positionClock();
-
-        // THEN the worst-case clock Y position is shifted only by 100 (not the full 200),
-        // so that it's at the same location as mUdfpsTop
-        assertThat(mClockPosition.clockY).isEqualTo(100);
-
-        // WHEN the clock position algorithm is run with the lowest burn in offset
-        givenLowestBurnInOffset();
-        positionClock();
-
-        // THEN lowest case starts at 0
-        assertThat(mClockPosition.clockY).isEqualTo(0);
-    }
-
-    @Test
-    public void clockPositionShiftsToAvoidUdfpsOnAOD_usesSpaceAboveClock() {
-        // GIVEN a center aligned clock
-        mClockTopAligned = false;
-
-        // GIVEN there's space at the top of the screen on LS (that's available to be used for
-        // burn-in on AOD)
-        mKeyguardStatusBarHeaderHeight = 150;
-
-        // GIVEN the bottom of the clock is beyond the top of UDFPS
-        mClockBottom = SCREEN_HEIGHT - 300;
-        mUdfpsTop = SCREEN_HEIGHT - 400;
-
-        // GIVEN it's AOD and the burn-in y value is 200
-        givenAOD();
-        givenMaxBurnInOffset(200);
-
-        // WHEN the clock position algorithm is run with the highest burn in offset
-        givenHighestBurnInOffset();
-        positionClock();
-
-        // THEN the algo should shift the clock up and use the area above the clock for
-        // burn-in since the burn in offset > space above clock
-        assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight);
-
-        // WHEN the clock position algorithm is run with the lowest burn in offset
-        givenLowestBurnInOffset();
-        positionClock();
-
-        // THEN lowest case starts at mCutoutTopInset (0 in this case)
-        assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset);
-    }
-
-    @Test
-    public void clockPositionShiftsToAvoidUdfpsOnAOD_usesMaxBurnInOffset() {
-        // GIVEN a center aligned clock
-        mClockTopAligned = false;
-
-        // GIVEN there's 200px space at the top of the screen on LS (that's available to be used for
-        // burn-in on AOD) but 50px are taken up by the cutout
-        mKeyguardStatusBarHeaderHeight = 200;
-        mCutoutTopInset = 50;
-
-        // GIVEN the bottom of the clock is beyond the top of UDFPS
-        mClockBottom = SCREEN_HEIGHT - 300;
-        mUdfpsTop = SCREEN_HEIGHT - 400;
-
-        // GIVEN it's AOD and the burn-in y value is only 25px (less than space above clock)
-        givenAOD();
-        int maxYBurnInOffset = 25;
-        givenMaxBurnInOffset(maxYBurnInOffset);
-
-        // WHEN the clock position algorithm is run with the highest burn in offset
-        givenHighestBurnInOffset();
-        positionClock();
-
-        // THEN the algo should shift the clock up and use the area above the clock for
-        // burn-in
-        assertThat(mClockPosition.clockY).isEqualTo(mKeyguardStatusBarHeaderHeight);
-
-        // WHEN the clock position algorithm is run with the lowest burn in offset
-        givenLowestBurnInOffset();
-        positionClock();
-
-        // THEN lowest case starts above mKeyguardStatusBarHeaderHeight
-        assertThat(mClockPosition.clockY).isEqualTo(
-                mKeyguardStatusBarHeaderHeight - 2 * maxYBurnInOffset);
-    }
-
-    @Test
-    public void clockPositionShiftsToMaximizeUdfpsBurnInMovement() {
-        // GIVEN a center aligned clock
-        mClockTopAligned = false;
-
-        // GIVEN there's 200px space at the top of the screen on LS (that's available to be used for
-        // burn-in on AOD) but 50px are taken up by the cutout
-        mKeyguardStatusBarHeaderHeight = 200;
-        mCutoutTopInset = 50;
-        int upperSpaceAvailable = mKeyguardStatusBarHeaderHeight - mCutoutTopInset;
-
-        // GIVEN the bottom of the clock and the top of UDFPS are 100px apart
-        mClockBottom = SCREEN_HEIGHT - 500;
-        mUdfpsTop = SCREEN_HEIGHT - 400;
-        float lowerSpaceAvailable = mUdfpsTop - mClockBottom;
-
-        // GIVEN it's AOD and the burn-in y value is 200
-        givenAOD();
-        givenMaxBurnInOffset(200);
-
-        // WHEN the clock position algorithm is run with the highest burn in offset
-        givenHighestBurnInOffset();
-        positionClock();
-
-        // THEN the algo should shift the clock up and use both the area above
-        // the clock and below the clock (vertically centered in its allowed area)
-        assertThat(mClockPosition.clockY).isEqualTo(
-                (int) (mCutoutTopInset + upperSpaceAvailable + lowerSpaceAvailable));
-
-        // WHEN the clock position algorithm is run with the lowest burn in offset
-        givenLowestBurnInOffset();
-        positionClock();
-
-        // THEN lowest case starts at mCutoutTopInset
-        assertThat(mClockPosition.clockY).isEqualTo(mCutoutTopInset);
-    }
-
     private void setSplitShadeTopMargin(int value) {
         when(mResources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin))
                 .thenReturn(value);
@@ -606,10 +159,6 @@
         when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).then(returnsFirstArg());
     }
 
-    private void givenLowestBurnInOffset() {
-        when(BurnInHelperKt.getBurnInOffset(anyInt(), anyBoolean())).thenReturn(0);
-    }
-
     private void givenMaxBurnInOffset(int offset) {
         when(mResources.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y_clock))
                 .thenReturn(offset);
@@ -617,12 +166,10 @@
     }
 
     private void givenAOD() {
-        mPanelExpansion = 1.f;
         mDark = 1.f;
     }
 
     private void givenLockScreen() {
-        mPanelExpansion = 1.f;
         mDark = 0.f;
     }
 
@@ -633,21 +180,11 @@
      */
     private void positionClock() {
         mClockPositionAlgorithm.setup(
-                mKeyguardStatusBarHeaderHeight,
-                mPanelExpansion,
-                mKeyguardStatusHeight,
-                mUserSwitchHeight,
-                0 /* userSwitchPreferredY */,
                 mDark,
                 ZERO_DRAG,
                 mBypassEnabled,
                 mUnlockedStackScrollerPadding,
-                mQsExpansion,
-                mCutoutTopInset,
-                mIsSplitShade,
-                mUdfpsTop,
-                mClockBottom,
-                mClockTopAligned);
+                mIsSplitShade);
         mClockPositionAlgorithm.run(mClockPosition);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index b39e38b..0b443675 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -73,6 +73,7 @@
 import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeHomeStatusBarViewModel;
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.StatusBarOperatorNameViewModel;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateController;
 import com.android.systemui.statusbar.window.StatusBarWindowStateListener;
@@ -1245,7 +1246,8 @@
         mSecureSettings = mock(SecureSettings.class);
 
         mShadeExpansionStateManager = new ShadeExpansionStateManager();
-        mCollapsedStatusBarViewModel = new FakeHomeStatusBarViewModel();
+        mCollapsedStatusBarViewModel = new FakeHomeStatusBarViewModel(
+                mock(StatusBarOperatorNameViewModel.class));
         mCollapsedStatusBarViewBinder = new FakeHomeStatusBarViewBinder();
 
         return new CollapsedStatusBarFragment(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImplTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImplTest.kt
index 320c148..7d101be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryImplTest.kt
@@ -48,11 +48,11 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-class CarrierConfigRepositoryTest : SysuiTestCase() {
+class CarrierConfigRepositoryImplTest : SysuiTestCase() {
     private val testDispatcher = UnconfinedTestDispatcher()
     private val testScope = TestScope(testDispatcher)
 
-    private lateinit var underTest: CarrierConfigRepository
+    private lateinit var underTest: CarrierConfigRepositoryImpl
     private lateinit var mockitoSession: MockitoSession
     private lateinit var carrierConfigCoreStartable: CarrierConfigCoreStartable
 
@@ -81,12 +81,11 @@
         }
 
         underTest =
-            CarrierConfigRepository(
+            CarrierConfigRepositoryImpl(
                 fakeBroadcastDispatcher,
                 carrierConfigManager,
                 dumpManager,
                 logger,
-                testScope.backgroundScope,
             )
 
         carrierConfigCoreStartable =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 2e0b7c6..d7456df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -58,6 +58,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.carrierConfigRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
 import com.android.systemui.statusbar.pipeline.mobile.util.FakeSubscriptionManagerProxy
@@ -68,7 +69,6 @@
 import com.android.systemui.statusbar.pipeline.wifi.data.repository.prod.WifiRepositoryImpl
 import com.android.systemui.testKosmos
 import com.android.systemui.user.data.repository.fakeUserRepository
-import com.android.systemui.user.data.repository.userRepository
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
@@ -209,14 +209,7 @@
                 wifiTableLogBuffer,
             )
 
-        carrierConfigRepository =
-            CarrierConfigRepository(
-                fakeBroadcastDispatcher,
-                mock(),
-                mock(),
-                logger,
-                testScope.backgroundScope,
-            )
+        carrierConfigRepository = kosmos.carrierConfigRepository
 
         connectionFactory =
             MobileConnectionRepositoryImpl.Factory(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorTest.kt
new file mode 100644
index 0000000..6da8aab
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.carrierConfigRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.createDefaultTestConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fake
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CarrierConfigInteractorTest : SysuiTestCase() {
+    val kosmos = testKosmos()
+    private val Kosmos.underTest by Kosmos.Fixture { kosmos.carrierConfigInteractor }
+
+    @Test
+    fun defaultDataSubscriptionCarrierConfig_tracksDefaultSubId() =
+        kosmos.runTest {
+            val carrierConfig1 = SystemUiCarrierConfig(1, createDefaultTestConfig())
+            val carrierConfig2 = SystemUiCarrierConfig(2, createDefaultTestConfig())
+
+            // Put some configs in so we can check by identity
+            carrierConfigRepository.fake.configsById[1] = carrierConfig1
+            carrierConfigRepository.fake.configsById[2] = carrierConfig2
+
+            val latest by collectLastValue(underTest.defaultDataSubscriptionCarrierConfig)
+
+            fakeMobileIconsInteractor.defaultDataSubId.value = 1
+
+            assertThat(latest).isEqualTo(carrierConfig1)
+
+            fakeMobileIconsInteractor.defaultDataSubId.value = 2
+
+            assertThat(latest).isEqualTo(carrierConfig2)
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
index 6326e73..89f2d3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt
@@ -37,7 +37,6 @@
 import android.telephony.satellite.SatelliteManager.SatelliteException
 import android.telephony.satellite.SatelliteModemStateCallback
 import android.telephony.satellite.SatelliteProvisionStateCallback
-import android.telephony.satellite.SatelliteSupportedStateCallback
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
@@ -52,6 +51,7 @@
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
+import java.util.function.Consumer
 import kotlin.test.Test
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
@@ -535,7 +535,7 @@
             runCurrent()
 
             val callback =
-                withArgCaptor<SatelliteSupportedStateCallback> {
+                withArgCaptor<Consumer<Boolean>> {
                     verify(satelliteManager).registerForSupportedStateChanged(any(), capture())
                 }
 
@@ -548,7 +548,7 @@
             verify(satelliteManager, times(1)).registerForNtnSignalStrengthChanged(any(), any())
 
             // WHEN satellite support turns off
-            callback.onSatelliteSupportedStateChanged(false)
+            callback.accept(false)
             runCurrent()
 
             // THEN listeners are unregistered
@@ -564,7 +564,7 @@
             runCurrent()
 
             val callback =
-                withArgCaptor<SatelliteSupportedStateCallback> {
+                withArgCaptor<Consumer<Boolean>> {
                     verify(satelliteManager).registerForSupportedStateChanged(any(), capture())
                 }
 
@@ -577,7 +577,7 @@
             verify(satelliteManager, times(0)).registerForNtnSignalStrengthChanged(any(), any())
 
             // WHEN satellite support turns on
-            callback.onSatelliteSupportedStateChanged(true)
+            callback.accept(true)
             runCurrent()
 
             // THEN listeners are registered
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 192d66c..af12d01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -167,7 +167,6 @@
 import com.android.systemui.util.time.SystemClock;
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.bubbles.Bubble;
 import com.android.wm.shell.bubbles.BubbleData;
 import com.android.wm.shell.bubbles.BubbleDataRepository;
@@ -184,6 +183,8 @@
 import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
 import com.android.wm.shell.bubbles.properties.BubbleProperties;
 import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -325,7 +326,9 @@
     @Mock
     private LauncherApps mLauncherApps;
     @Mock
-    private WindowManagerShellWrapper mWindowManagerShellWrapper;
+    private DisplayInsetsController mDisplayInsetsController;
+    @Mock
+    private DisplayImeController mDisplayImeController;
     @Mock
     private BubbleLogger mBubbleLogger;
     @Mock
@@ -503,7 +506,7 @@
                         mContext,
                         mock(NotificationManager.class),
                         mock(NotificationSettingsInteractor.class)
-                        );
+                );
         interruptionDecisionProvider.start();
 
         mShellTaskOrganizer = new ShellTaskOrganizer(mock(ShellInit.class),
@@ -523,7 +526,8 @@
                 mDataRepository,
                 mStatusBarService,
                 mWindowManager,
-                mWindowManagerShellWrapper,
+                mDisplayInsetsController,
+                mDisplayImeController,
                 mUserManager,
                 mLauncherApps,
                 mBubbleLogger,
@@ -1430,9 +1434,12 @@
                 mPositioner,
                 mBubbleController.getStackView(),
                 new BubbleIconFactory(mContext,
-                        mContext.getResources().getDimensionPixelSize(com.android.wm.shell.R.dimen.bubble_size),
-                        mContext.getResources().getDimensionPixelSize(com.android.wm.shell.R.dimen.bubble_badge_size),
-                        mContext.getResources().getColor(com.android.launcher3.icons.R.color.important_conversation),
+                        mContext.getResources().getDimensionPixelSize(
+                                com.android.wm.shell.R.dimen.bubble_size),
+                        mContext.getResources().getDimensionPixelSize(
+                                com.android.wm.shell.R.dimen.bubble_badge_size),
+                        mContext.getResources().getColor(
+                                com.android.launcher3.icons.R.color.important_conversation),
                         mContext.getResources().getDimensionPixelSize(
                                 com.android.internal.R.dimen.importance_ring_stroke_width)),
                 bubble,
diff --git a/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt b/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
index 76fc611..25d1c37 100644
--- a/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
+++ b/packages/SystemUI/tests/utils/src/android/internal/statusbar/FakeStatusBarService.kt
@@ -433,6 +433,8 @@
 
     override fun showRearDisplayDialog(currentBaseState: Int) {}
 
+    override fun unbundleNotification(key: String) {}
+
     companion object {
         const val DEFAULT_DISPLAY_ID = Display.DEFAULT_DISPLAY
         const val SECONDARY_DISPLAY_ID = 2
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
index 3e44364..252c70a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java
@@ -342,7 +342,7 @@
     }
 
     /** Delegates to {@link android.testing.TestableResources#addOverride(int, Object)}. */
-    protected void overrideResource(int resourceId, Object value) {
+    public void overrideResource(int resourceId, Object value) {
         mContext.getOrCreateTestableResources().addOverride(resourceId, value);
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/view/ChoreographerUtilsKosmos.kt
similarity index 76%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/view/ChoreographerUtilsKosmos.kt
index 580f617..266cb31 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/view/ChoreographerUtilsKosmos.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.common.ui.view
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.fakeChoreographerUtils: FakeChoreographerUtils by
+    Kosmos.Fixture { FakeChoreographerUtils() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.kt
similarity index 61%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.kt
index 580f617..57c8fd0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.kt
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.communal.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.scene.domain.interactor.sceneInteractor
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.communalBackActionInteractor by
+    Kosmos.Fixture {
+        CommunalBackActionInteractor(
+            communalInteractor = communalInteractor,
+            communalSceneInteractor = communalSceneInteractor,
+            sceneInteractor = sceneInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
index ad92b31..89aad4b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalInteractorKosmos.kt
@@ -86,12 +86,8 @@
 }
 
 suspend fun Kosmos.setCommunalV2Enabled(enabled: Boolean) {
-    setCommunalV2ConfigEnabled(true)
-    if (enabled) {
-        fakeUserRepository.asMainUser()
-    } else {
-        fakeUserRepository.asDefaultUser()
-    }
+    setCommunalV2ConfigEnabled(enabled)
+    setCommunalEnabled(enabled)
 }
 
 suspend fun Kosmos.setCommunalAvailable(available: Boolean) {
@@ -103,10 +99,6 @@
 }
 
 suspend fun Kosmos.setCommunalV2Available(available: Boolean) {
-    setCommunalV2ConfigEnabled(true)
-    setCommunalEnabled(available)
-    with(fakeKeyguardRepository) {
-        setIsEncryptedOrLockdown(!available)
-        setKeyguardShowing(available)
-    }
+    setCommunalV2ConfigEnabled(available)
+    setCommunalAvailable(available)
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
index b407b1b..c2d2392 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/ui/viewmodel/CommunalToDreamButtonViewModelKosmos.kt
@@ -17,8 +17,11 @@
 package com.android.systemui.communal.ui.viewmodel
 
 import android.service.dream.dreamManager
+import com.android.internal.logging.uiEventLogger
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.plugins.activityStarter
 import com.android.systemui.statusbar.policy.batteryController
 
 val Kosmos.communalToDreamButtonViewModel by
@@ -26,6 +29,9 @@
         CommunalToDreamButtonViewModel(
             backgroundContext = testDispatcher,
             batteryController = batteryController,
+            settingsInteractor = communalSettingsInteractor,
+            activityStarter = activityStarter,
             dreamManager = dreamManager,
+            uiEventLogger = uiEventLogger,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayWindowPropertiesRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayWindowPropertiesRepository.kt
index 534ded5..9012393 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayWindowPropertiesRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayWindowPropertiesRepository.kt
@@ -58,4 +58,26 @@
     fun insert(instance: DisplayWindowProperties) {
         properties.put(instance.displayId, instance.windowType, instance)
     }
+
+    /** inserts an entry, mocking everything except the context. */
+    fun insertForContext(displayId: Int, windowType: Int, context: Context) {
+        properties.put(
+            displayId,
+            windowType,
+            DisplayWindowProperties(
+                displayId = displayId,
+                windowType = windowType,
+                context = context,
+                windowManager = mock(),
+                layoutInflater = mock(),
+            ),
+        )
+    }
+
+    /** Whether the repository contains an entry already. */
+    fun contains(displayId: Int, windowType: Int): Boolean =
+        properties.contains(displayId, windowType)
+
+    /** Removes all the entries. */
+    fun clear() = properties.clear()
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
index 4513cc0..dad8569 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/EnableSceneContainer.kt
@@ -18,7 +18,6 @@
 
 import android.platform.test.annotations.EnableFlags
 import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
-import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
 import com.android.systemui.Flags.FLAG_NOTIFICATION_AVALANCHE_THROTTLE_HUN
 import com.android.systemui.Flags.FLAG_PREDICTIVE_BACK_SYSUI
 import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
@@ -29,7 +28,6 @@
  */
 @EnableFlags(
     FLAG_KEYGUARD_WM_STATE_REFACTOR,
-    FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT,
     FLAG_NOTIFICATION_AVALANCHE_THROTTLE_HUN,
     FLAG_PREDICTIVE_BACK_SYSUI,
     FLAG_SCENE_CONTAINER,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
index d9235cc..2f7936a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/FeatureFlagsClassicKosmos.kt
@@ -34,7 +34,6 @@
     Kosmos.Fixture {
         FakeFeatureFlagsClassic().apply {
             set(Flags.FULL_SCREEN_USER_SWITCHER, false)
-            set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false)
             set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
             set(Flags.NSSL_DEBUG_LINES, false)
             set(Flags.COMMUNAL_SERVICE_ENABLED, false)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
index 548b564..5d20669 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt
@@ -30,7 +30,7 @@
     override val pickerIconResourceId: Int = 0,
 ) : KeyguardQuickAffordanceConfig {
 
-    var onTriggeredResult: OnTriggeredResult = OnTriggeredResult.Handled
+    var onTriggeredResult: OnTriggeredResult = OnTriggeredResult.Handled(false)
 
     private val _lockScreenState =
         MutableStateFlow<KeyguardQuickAffordanceConfig.LockScreenState>(
@@ -41,9 +41,7 @@
 
     override fun pickerName(): String = pickerName
 
-    override fun onTriggered(
-        expandable: Expandable?,
-    ): OnTriggeredResult {
+    override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
         return onTriggeredResult
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigKosmos.kt
new file mode 100644
index 0000000..5683248
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/GlanceableHubQuickAffordanceConfigKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.data.quickaffordance
+
+import android.content.applicationContext
+import com.android.systemui.communal.data.repository.communalSceneRepository
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+
+val Kosmos.glanceableHubQuickAffordanceConfig by
+    Kosmos.Fixture {
+        GlanceableHubQuickAffordanceConfig(
+            context = applicationContext,
+            communalInteractor = communalInteractor,
+            communalSceneRepository = communalSceneRepository,
+            communalSettingsInteractor = communalSettingsInteractor,
+            sceneInteractor = sceneInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/LocalUserSelectionManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/LocalUserSelectionManagerKosmos.kt
index 21d1a76..328338b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/LocalUserSelectionManagerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/quickaffordance/LocalUserSelectionManagerKosmos.kt
@@ -18,6 +18,7 @@
 
 import android.content.applicationContext
 import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.settings.userFileManager
 import com.android.systemui.settings.userTracker
@@ -28,6 +29,7 @@
             context = applicationContext,
             userFileManager = userFileManager,
             userTracker = userTracker,
+            communalSettingsInteractor = communalSettingsInteractor,
             broadcastDispatcher = broadcastDispatcher,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index 49a8c18..6df2318c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -59,7 +59,6 @@
             defaultShortcutsSection = mock(),
             defaultAmbientIndicationAreaSection = Optional.of(mock()),
             defaultSettingsPopupMenuSection = mock(),
-            defaultStatusViewSection = mock(),
             defaultStatusBarSection = mock(),
             defaultNotificationStackScrollLayoutSection = mock(),
             aodNotificationIconsSection = mock(),
@@ -81,7 +80,6 @@
             defaultShortcutsSection = mock(),
             defaultAmbientIndicationAreaSection = Optional.of(mock()),
             defaultSettingsPopupMenuSection = mock(),
-            defaultStatusViewSection = mock(),
             defaultStatusBarSection = mock(),
             splitShadeNotificationStackScrollLayoutSection = mock(),
             splitShadeGuidelines = mock(),
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 4a6e273..3de8093 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -54,6 +54,7 @@
         fromGoneTransitionInteractor: FromGoneTransitionInteractor = mock(),
         fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor = mock(),
         fromOccludedTransitionInteractor: FromOccludedTransitionInteractor = mock(),
+        fromAlternateBouncerTransitionInteractor: FromAlternateBouncerTransitionInteractor = mock(),
         powerInteractor: PowerInteractor = PowerInteractorFactory.create().powerInteractor,
         testScope: CoroutineScope = TestScope(),
     ): WithDependencies {
@@ -84,6 +85,9 @@
                 fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
                 fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
                 fromOccludedTransitionInteractor = { fromOccludedTransitionInteractor },
+                fromAlternateBouncerTransitionInteractor = {
+                    fromAlternateBouncerTransitionInteractor
+                },
                 applicationScope = testScope,
             ),
         )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
index da261bf..f5f8ef7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt
@@ -38,6 +38,7 @@
             fromGoneTransitionInteractor = { fromGoneTransitionInteractor },
             fromLockscreenTransitionInteractor = { fromLockscreenTransitionInteractor },
             fromOccludedTransitionInteractor = { fromOccludedTransitionInteractor },
+            fromAlternateBouncerTransitionInteractor = { fromAlternateBouncerTransitionInteractor },
             applicationScope = testScope.backgroundScope,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceHapticViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceHapticViewModelKosmos.kt
new file mode 100644
index 0000000..d857157
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceHapticViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceHapticViewModel
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordanceViewModel
+import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.flow.Flow
+
+val Kosmos.keyguardQuickAffordanceHapticViewModelFactory by
+    Kosmos.Fixture {
+        object : KeyguardQuickAffordanceHapticViewModel.Factory {
+            override fun create(
+                quickAffordanceViewModel: Flow<KeyguardQuickAffordanceViewModel>
+            ): KeyguardQuickAffordanceHapticViewModel =
+                KeyguardQuickAffordanceHapticViewModel(
+                    quickAffordanceViewModel,
+                    keyguardQuickAffordanceInteractor,
+                )
+        }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
index 009d17e..3b1199a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorKosmos.kt
@@ -21,6 +21,7 @@
 import com.android.internal.widget.lockPatternUtils
 import com.android.keyguard.logging.KeyguardQuickAffordancesLogger
 import com.android.systemui.animation.dialogTransitionAnimator
+import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
 import com.android.systemui.dock.dockManager
 import com.android.systemui.flags.featureFlagsClassic
 import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
@@ -52,6 +53,7 @@
         devicePolicyManager = devicePolicyManager,
         dockManager = dockManager,
         biometricSettingsRepository = biometricSettingsRepository,
+        communalSettingsInteractor = communalSettingsInteractor,
         backgroundDispatcher = testDispatcher,
         appContext = applicationContext,
         sceneInteractor = { sceneInteractor },
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/BlurConfigKosmos.kt
similarity index 76%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/BlurConfigKosmos.kt
index 580f617..0e24805 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/BlurConfigKosmos.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.keyguard.ui.transitions
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.blurConfig by Fixture { BlurConfig(minBlurRadiusPx = 1.0f, maxBlurRadiusPx = 100.0f) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeBouncerTransition.kt
similarity index 71%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeBouncerTransition.kt
index 580f617..15d00d9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/transitions/FakeBouncerTransition.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.keyguard.ui.transitions
 
-import com.android.systemui.kosmos.Kosmos
+import kotlinx.coroutines.flow.MutableStateFlow
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+class FakeBouncerTransition : PrimaryBouncerTransition {
+    override val windowBlurRadius: MutableStateFlow<Float> = MutableStateFlow(0.0f)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelKosmos.kt
index b03624b..7989244 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -19,13 +19,16 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
+@OptIn(ExperimentalCoroutinesApi::class)
 val Kosmos.alternateBouncerToPrimaryBouncerTransitionViewModel by Fixture {
     AlternateBouncerToPrimaryBouncerTransitionViewModel(
         animationFlow = keyguardTransitionAnimationFlow,
         shadeDependentFlows = shadeDependentFlows,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelKosmos.kt
deleted file mode 100644
index 24201d7..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodAlphaViewModelKosmos.kt
+++ /dev/null
@@ -1,36 +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.
- */
-
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
-package com.android.systemui.keyguard.ui.viewmodel
-
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-
-val Kosmos.aodAlphaViewModel by Fixture {
-    AodAlphaViewModel(
-        keyguardTransitionInteractor = keyguardTransitionInteractor,
-        goneToAodTransitionViewModel = goneToAodTransitionViewModel,
-        goneToDozingTransitionViewModel = goneToDozingTransitionViewModel,
-        keyguardInteractor = keyguardInteractor,
-        sceneInteractor = sceneInteractor,
-    )
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerViewModelKosmos.kt
index 5e6d605..faa290be 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AodToPrimaryBouncerViewModelKosmos.kt
@@ -17,11 +17,15 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 @OptIn(ExperimentalCoroutinesApi::class)
 val Kosmos.aodToPrimaryBouncerTransitionViewModel by Fixture {
-    AodToPrimaryBouncerTransitionViewModel(animationFlow = keyguardTransitionAnimationFlow)
+    AodToPrimaryBouncerTransitionViewModel(
+        animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
+    )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt
index dc6b26f..d3ccb29 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -25,5 +26,6 @@
 val Kosmos.dozingToPrimaryBouncerTransitionViewModel by Fixture {
     DozingToPrimaryBouncerTransitionViewModel(
         animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
index e473107..abbfa93 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelKosmos.kt
@@ -87,7 +87,6 @@
             primaryBouncerToLockscreenTransitionViewModel,
         screenOffAnimationController = screenOffAnimationController,
         aodBurnInViewModel = aodBurnInViewModel,
-        aodAlphaViewModel = aodAlphaViewModel,
         shadeInteractor = shadeInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt
index f094f22..68280d7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToPrimaryBouncerTransitionViewModelKosmos.kt
@@ -19,6 +19,7 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -27,5 +28,6 @@
     LockscreenToPrimaryBouncerTransitionViewModel(
         shadeDependentFlows = shadeDependentFlows,
         animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt
index 8d88730..043a49f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToAodTransitionViewModelKosmos.kt
@@ -20,6 +20,7 @@
 
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -28,5 +29,6 @@
     PrimaryBouncerToAodTransitionViewModel(
         deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
         animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt
index d4e4b8c..59ea2c9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToDozingTransitionViewModelKosmos.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -27,5 +28,6 @@
     PrimaryBouncerToDozingTransitionViewModel(
         deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
         animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
index 09233af..4fe18fb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGlanceableHubTransitionViewModelKosmos.kt
@@ -17,11 +17,13 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 
 val Kosmos.primaryBouncerToGlanceableHubTransitionViewModel by Fixture {
     PrimaryBouncerToGlanceableHubTransitionViewModel(
-        animationFlow = keyguardTransitionAnimationFlow
+        animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
index d6edea2..b470ab1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelKosmos.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.bouncer.domain.interactor.mockPrimaryBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardDismissActionInteractor
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.statusbar.sysuiStatusBarStateController
@@ -33,5 +34,6 @@
         keyguardDismissActionInteractor = { keyguardDismissActionInteractor },
         bouncerToGoneFlows = bouncerToGoneFlows,
         animationFlow = keyguardTransitionAnimationFlow,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt
index 76478cb..c344775 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToLockscreenTransitionViewModelKosmos.kt
@@ -19,6 +19,7 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.blurConfig
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -27,5 +28,6 @@
     PrimaryBouncerToLockscreenTransitionViewModel(
         animationFlow = keyguardTransitionAnimationFlow,
         shadeDependentFlows = shadeDependentFlows,
+        blurConfig = blurConfig,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
index d941fb0..4383560 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/GeneralKosmos.kt
@@ -17,6 +17,7 @@
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
+import org.mockito.kotlin.verify
 
 var Kosmos.testDispatcher by Fixture { StandardTestDispatcher() }
 
@@ -82,6 +83,32 @@
 }
 
 /** Retrieve the current value of this [StateFlow] safely. See `currentValue(TestScope)`. */
+fun <T> Kosmos.currentValue(fn: () -> T) = testScope.currentValue(fn)
+
+/**
+ * Retrieve the result of [fn] after running all pending tasks. Do not use to retrieve the value of
+ * a flow directly; for that, use either `currentValue(StateFlow)` or [collectLastValue]
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+fun <T> TestScope.currentValue(fn: () -> T): T {
+    runCurrent()
+    return fn()
+}
+
+/** Retrieve the result of [fn] after running all pending tasks. See `TestScope.currentValue(fn)` */
 fun <T> Kosmos.currentValue(stateFlow: StateFlow<T>): T {
     return testScope.currentValue(stateFlow)
 }
+
+/** Safely verify that a mock has been called after the test scope has caught up */
+@OptIn(ExperimentalCoroutinesApi::class)
+fun <T> TestScope.verifyCurrent(mock: T): T {
+    runCurrent()
+    return verify(mock)
+}
+
+/**
+ * Safely verify that a mock has been called after the test scope has caught up. See
+ * `TestScope.verifyCurrent`
+ */
+fun <T> Kosmos.verifyCurrent(mock: T) = testScope.verifyCurrent(mock)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 41cfcea..39f1ad4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -63,6 +63,7 @@
 import com.android.systemui.scene.domain.startable.scrimStartable
 import com.android.systemui.scene.sceneContainerConfig
 import com.android.systemui.scene.shared.model.sceneDataSource
+import com.android.systemui.scene.ui.view.mockWindowRootViewProvider
 import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -191,4 +192,5 @@
     }
     val disableFlagsInteractor by lazy { kosmos.disableFlagsInteractor }
     val fakeDisableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
+    val mockWindowRootViewProvider by lazy { kosmos.mockWindowRootViewProvider }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/mediarouter/data/repository/FakeMediaRouterRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/mediarouter/data/repository/FakeMediaRouterRepository.kt
index 8aa7a03..d5637cb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/mediarouter/data/repository/FakeMediaRouterRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/mediarouter/data/repository/FakeMediaRouterRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.mediarouter.data.repository
 
+import android.media.projection.StopReason
 import com.android.systemui.statusbar.policy.CastDevice
 import kotlinx.coroutines.flow.MutableStateFlow
 
@@ -25,7 +26,7 @@
     var lastStoppedDevice: CastDevice? = null
         private set
 
-    override fun stopCasting(device: CastDevice) {
+    override fun stopCasting(device: CastDevice, @StopReason stopReason: Int) {
         lastStoppedDevice = device
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt
index ab1c181..aa29808 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/QSTileStateSubject.kt
@@ -45,7 +45,6 @@
             other ?: return
         }
         check("icon").that(actual.icon).isEqualTo(other.icon)
-        check("iconRes").that(actual.iconRes).isEqualTo(other.iconRes)
         check("label").that(actual.label).isEqualTo(other.label)
         check("activationState").that(actual.activationState).isEqualTo(other.activationState)
         check("secondaryLabel").that(actual.secondaryLabel).isEqualTo(other.secondaryLabel)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
index f52572a..f5eebb4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/FakeSceneDataSource.kt
@@ -19,13 +19,13 @@
 import com.android.compose.animation.scene.OverlayKey
 import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.TransitionKey
+import com.android.systemui.kosmos.currentValue
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.test.TestScope
 
-class FakeSceneDataSource(
-    initialSceneKey: SceneKey,
-) : SceneDataSource {
+class FakeSceneDataSource(initialSceneKey: SceneKey, val testScope: TestScope) : SceneDataSource {
 
     private val _currentScene = MutableStateFlow(initialSceneKey)
     override val currentScene: StateFlow<SceneKey> = _currentScene.asStateFlow()
@@ -33,18 +33,20 @@
     private val _currentOverlays = MutableStateFlow<Set<OverlayKey>>(emptySet())
     override val currentOverlays: StateFlow<Set<OverlayKey>> = _currentOverlays.asStateFlow()
 
-    var isPaused = false
-        private set
+    private var _isPaused = false
+    val isPaused
+        get() = testScope.currentValue { _isPaused }
 
-    var pendingScene: SceneKey? = null
-        private set
+    private var _pendingScene: SceneKey? = null
+    val pendingScene
+        get() = testScope.currentValue { _pendingScene }
 
     var pendingOverlays: Set<OverlayKey>? = null
         private set
 
     override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
-        if (isPaused) {
-            pendingScene = toScene
+        if (_isPaused) {
+            _pendingScene = toScene
         } else {
             _currentScene.value = toScene
         }
@@ -55,7 +57,7 @@
     }
 
     override fun showOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
-        if (isPaused) {
+        if (_isPaused) {
             pendingOverlays = (pendingOverlays ?: currentOverlays.value) + overlay
         } else {
             _currentOverlays.value += overlay
@@ -63,7 +65,7 @@
     }
 
     override fun hideOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
-        if (isPaused) {
+        if (_isPaused) {
             pendingOverlays = (pendingOverlays ?: currentOverlays.value) - overlay
         } else {
             _currentOverlays.value -= overlay
@@ -82,9 +84,9 @@
      * last one will be remembered.
      */
     fun pause() {
-        check(!isPaused) { "Can't pause what's already paused!" }
+        check(!_isPaused) { "Can't pause what's already paused!" }
 
-        isPaused = true
+        _isPaused = true
     }
 
     /**
@@ -100,15 +102,12 @@
      *
      * If [expectedScene] is provided, will assert that it's indeed the latest called.
      */
-    fun unpause(
-        force: Boolean = false,
-        expectedScene: SceneKey? = null,
-    ) {
-        check(force || isPaused) { "Can't unpause what's already not paused!" }
+    fun unpause(force: Boolean = false, expectedScene: SceneKey? = null) {
+        check(force || _isPaused) { "Can't unpause what's already not paused!" }
 
-        isPaused = false
-        pendingScene?.let { _currentScene.value = it }
-        pendingScene = null
+        _isPaused = false
+        _pendingScene?.let { _currentScene.value = it }
+        _pendingScene = null
         pendingOverlays?.let { _currentOverlays.value = it }
         pendingOverlays = null
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/SceneDataSourceKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/SceneDataSourceKosmos.kt
index f519686..7eebfc3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/SceneDataSourceKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/model/SceneDataSourceKosmos.kt
@@ -19,13 +19,12 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
 import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.scene.initialSceneKey
 import com.android.systemui.scene.sceneContainerConfig
 
 val Kosmos.fakeSceneDataSource by Fixture {
-    FakeSceneDataSource(
-        initialSceneKey = initialSceneKey,
-    )
+    FakeSceneDataSource(initialSceneKey = initialSceneKey, testScope = testScope)
 }
 
 val Kosmos.sceneDataSourceDelegator by Fixture {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt
index 5c91dc8..e6ba9a5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/view/WindowRootViewKosmos.kt
@@ -17,6 +17,9 @@
 package com.android.systemui.scene.ui.view
 
 import com.android.systemui.kosmos.Kosmos
+import javax.inject.Provider
 import org.mockito.kotlin.mock
 
 val Kosmos.mockShadeRootView by Kosmos.Fixture { mock<WindowRootView>() }
+val Kosmos.mockWindowRootViewProvider by
+    Kosmos.Fixture { Provider<WindowRootView> { mock<WindowRootView>() } }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/screenrecord/data/repository/FakeScreenRecordRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/screenrecord/data/repository/FakeScreenRecordRepository.kt
index 30b4763..4c9e174 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/screenrecord/data/repository/FakeScreenRecordRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/screenrecord/data/repository/FakeScreenRecordRepository.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.screenrecord.data.repository
 
+import android.media.projection.StopReason
 import com.android.systemui.screenrecord.data.model.ScreenRecordModel
 import kotlinx.coroutines.flow.MutableStateFlow
 
@@ -25,7 +26,7 @@
 
     var stopRecordingInvoked = false
 
-    override suspend fun stopRecording() {
+    override suspend fun stopRecording(@StopReason stopReason: Int) {
         stopRecordingInvoked = true
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/NotificationShadeWindowViewKosmos.kt
similarity index 76%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/shade/NotificationShadeWindowViewKosmos.kt
index 580f617..18c44ba 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/NotificationShadeWindowViewKosmos.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.shade
 
 import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+var Kosmos.notificationShadeWindowView by Kosmos.Fixture { mock<NotificationShadeWindowView>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerKosmos.kt
new file mode 100644
index 0000000..67dd0ad
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeDisplayChangeLatencyTrackerKosmos.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import com.android.internal.logging.latencyTracker
+import com.android.systemui.common.ui.data.repository.configurationRepository
+import com.android.systemui.common.ui.view.fakeChoreographerUtils
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.ui.view.mockShadeRootView
+import java.util.Optional
+
+val Kosmos.shadeDisplayChangeLatencyTracker by Fixture {
+    ShadeDisplayChangeLatencyTracker(
+        Optional.of(mockShadeRootView),
+        configurationRepository,
+        latencyTracker,
+        testScope.backgroundScope,
+        fakeChoreographerUtils,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
index 4dcd220..3ed7302 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/ShadeAnimationRepositoryKosmos.kt
@@ -16,6 +16,14 @@
 
 package com.android.systemui.shade.data.repository
 
+import android.content.applicationContext
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.shade.domain.interactor.ShadeDialogContextInteractor
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
 
 val Kosmos.shadeAnimationRepository by Kosmos.Fixture { ShadeAnimationRepository() }
+val Kosmos.shadeDialogContextInteractor by
+    Kosmos.Fixture {
+        mock<ShadeDialogContextInteractor> { on { context } doReturn applicationContext }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
index f2af619..4af5e7d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
@@ -20,22 +20,23 @@
 import android.window.WindowContext
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.scene.ui.view.mockShadeRootView
+import com.android.systemui.shade.ShadeDisplayChangeLatencyTracker
 import com.android.systemui.shade.ShadeWindowLayoutParams
 import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
-import java.util.Optional
 import org.mockito.kotlin.mock
 
 val Kosmos.shadeLayoutParams by Kosmos.Fixture { ShadeWindowLayoutParams.create(mockedContext) }
 
 val Kosmos.mockedWindowContext by Kosmos.Fixture { mock<WindowContext>() }
+val Kosmos.mockedShadeDisplayChangeLatencyTracker by
+    Kosmos.Fixture { mock<ShadeDisplayChangeLatencyTracker>() }
 val Kosmos.shadeDisplaysInteractor by
     Kosmos.Fixture {
         ShadeDisplaysInteractor(
-            Optional.of(mockShadeRootView),
             fakeShadeDisplaysRepository,
             mockedWindowContext,
             testScope.backgroundScope,
             testScope.backgroundScope.coroutineContext,
+            mockedShadeDisplayChangeLatencyTracker,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionControllerKosmos.kt
index 8865573..9f4091c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionControllerKosmos.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 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.
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
index e4a3896..1a451ce 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerKosmos.kt
@@ -36,7 +36,7 @@
 import com.android.systemui.statusbar.policy.configurationController
 import com.android.systemui.statusbar.policy.splitShadeStateController
 
-val Kosmos.lockscreenShadeTransitionController by Fixture {
+var Kosmos.lockscreenShadeTransitionController by Fixture {
     LockscreenShadeTransitionController(
         statusBarStateController = sysuiStatusBarStateController,
         logger = lsShadeTransitionLogger,
@@ -62,6 +62,6 @@
         splitShadeStateController = splitShadeStateController,
         shadeLockscreenInteractorLazy = { shadeLockscreenInteractor },
         naturalScrollingSettingObserver = naturalScrollingSettingObserver,
-        lazyQSSceneAdapter = { qsSceneAdapter }
+        lazyQSSceneAdapter = { qsSceneAdapter },
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerKosmos.kt
index 5523bd6..8a68eef 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerKosmos.kt
@@ -20,10 +20,6 @@
 import com.android.systemui.kosmos.Kosmos.Fixture
 import org.mockito.kotlin.mock
 
-var Kosmos.singleShadeLockScreenOverScroller by Fixture {
-    mock<SingleShadeLockScreenOverScroller>()
-}
-
 var Kosmos.singleShadeLockScreenOverScrollerFactory by Fixture {
-    SingleShadeLockScreenOverScroller.Factory { _ -> singleShadeLockScreenOverScroller }
+    mock<SingleShadeLockScreenOverScroller.Factory>()
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorKosmos.kt
new file mode 100644
index 0000000..0025ad4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/featurepods/media/domain/interactor/MediaControlChipInteractorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.featurepods.media.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
+
+val Kosmos.mediaControlChipInteractor: MediaControlChipInteractor by
+    Kosmos.Fixture {
+        MediaControlChipInteractor(
+            applicationScope = applicationCoroutineScope,
+            mediaFilterRepository = mediaFilterRepository,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationContentExtractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationContentExtractor.kt
new file mode 100644
index 0000000..680e0de
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationContentExtractor.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.promoted
+
+import android.app.Notification
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
+import org.junit.Assert
+
+class FakePromotedNotificationContentExtractor : PromotedNotificationContentExtractor {
+    @JvmField
+    val contentForEntry = mutableMapOf<NotificationEntry, PromotedNotificationContentModel?>()
+    @JvmField val extractCalls = mutableListOf<Pair<NotificationEntry, Notification.Builder>>()
+
+    override fun extractContent(
+        entry: NotificationEntry,
+        recoveredBuilder: Notification.Builder,
+    ): PromotedNotificationContentModel? {
+        extractCalls.add(entry to recoveredBuilder)
+
+        if (contentForEntry.isEmpty()) {
+            // If *no* entries are set, just return null for everything.
+            return null
+        } else {
+            // If entries *are* set, fail on unexpected ones.
+            Assert.assertTrue(contentForEntry.containsKey(entry))
+            return contentForEntry.get(entry)
+        }
+    }
+
+    fun resetForEntry(entry: NotificationEntry, content: PromotedNotificationContentModel?) {
+        contentForEntry.clear()
+        contentForEntry.put(entry, content)
+        extractCalls.clear()
+    }
+
+    fun verifyZeroExtractCalls() {
+        Assert.assertTrue(extractCalls.isEmpty())
+    }
+
+    fun verifyOneExtractCall() {
+        Assert.assertEquals(1, extractCalls.size)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationsProvider.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationsProvider.kt
deleted file mode 100644
index 88caf6e..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/FakePromotedNotificationsProvider.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.promoted
-
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-
-class FakePromotedNotificationsProvider : PromotedNotificationsProvider {
-    val promotedEntries = mutableSetOf<NotificationEntry>()
-
-    override fun shouldPromote(entry: NotificationEntry): Boolean {
-        return promotedEntries.contains(entry)
-    }
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
index 5e9f12b..912d502 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationContentExtractorKosmos.kt
@@ -21,9 +21,5 @@
 
 var Kosmos.promotedNotificationContentExtractor by
     Kosmos.Fixture {
-        PromotedNotificationContentExtractor(
-            promotedNotificationsProvider,
-            applicationContext,
-            promotedNotificationLogger,
-        )
+        PromotedNotificationContentExtractorImpl(applicationContext, promotedNotificationLogger)
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
index 7126933..3fddd47c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
@@ -65,9 +65,8 @@
 import com.android.systemui.statusbar.notification.icon.IconBuilder
 import com.android.systemui.statusbar.notification.icon.IconManager
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractor
+import com.android.systemui.statusbar.notification.promoted.PromotedNotificationContentExtractorImpl
 import com.android.systemui.statusbar.notification.promoted.PromotedNotificationLogger
-import com.android.systemui.statusbar.notification.promoted.PromotedNotificationsProviderImpl
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.CoordinateOnClickListener
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpandableNotificationRowLogger
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener
@@ -222,16 +221,10 @@
                 Mockito.mock(LauncherApps::class.java, STUB_ONLY),
                 Mockito.mock(ConversationNotificationManager::class.java, STUB_ONLY),
             )
-
-        val promotedNotificationsProvider = PromotedNotificationsProviderImpl()
-        val promotedNotificationLog = logcatLogBuffer("PromotedNotifLog")
-        val promotedNotificationLogger = PromotedNotificationLogger(promotedNotificationLog)
-
         val promotedNotificationContentExtractor =
-            PromotedNotificationContentExtractor(
-                promotedNotificationsProvider,
+            PromotedNotificationContentExtractorImpl(
                 context,
-                promotedNotificationLogger,
+                PromotedNotificationLogger(logcatLogBuffer("PromotedNotifLog")),
             )
 
         mContentBinder =
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryKosmos.kt
similarity index 73%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryKosmos.kt
index 580f617..02ae3ad 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/AirplaneModeRepositoryKosmos.kt
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.statusbar.pipeline.airplane.data.repository
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.airplaneModeRepository by Kosmos.Fixture { FakeAirplaneModeRepository() }
+
+val AirplaneModeRepository.fake
+    get() = this as FakeAirplaneModeRepository
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
index 74b2da4..c30124c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/data/repository/FakeAirplaneModeRepository.kt
@@ -17,14 +17,12 @@
 package com.android.systemui.statusbar.pipeline.airplane.data.repository
 
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
 
 class FakeAirplaneModeRepository : AirplaneModeRepository {
 
-    private val _isAirplaneMode = MutableStateFlow(false)
-    override val isAirplaneMode: StateFlow<Boolean> = _isAirplaneMode
+    override val isAirplaneMode = MutableStateFlow(false)
 
     override suspend fun setIsAirplaneMode(isEnabled: Boolean) {
-        _isAirplaneMode.value = isEnabled
+        isAirplaneMode.value = isEnabled
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
index 99ed4f0..62d7601d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/airplane/domain/interactor/AirplaneModeInteractorKosmos.kt
@@ -17,15 +17,15 @@
 package com.android.systemui.statusbar.pipeline.airplane.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
+import com.android.systemui.statusbar.pipeline.airplane.data.repository.airplaneModeRepository
 import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepository
-import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
+import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository
 
 val Kosmos.airplaneModeInteractor: AirplaneModeInteractor by
     Kosmos.Fixture {
         AirplaneModeInteractor(
-            FakeAirplaneModeRepository(),
-            FakeConnectivityRepository(),
+            airplaneModeRepository,
+            connectivityRepository,
             mobileConnectionsRepository,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryKosmos.kt
similarity index 73%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryKosmos.kt
index 580f617..a6431af 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepositoryKosmos.kt
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.statusbar.pipeline.mobile.data.repository
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.carrierConfigRepository: CarrierConfigRepository by Fixture {
+    FakeCarrierConfigRepository()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeCarrierConfigRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeCarrierConfigRepository.kt
new file mode 100644
index 0000000..adf6ca1
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/FakeCarrierConfigRepository.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.mobile.data.repository
+
+import android.os.PersistableBundle
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+
+class FakeCarrierConfigRepository : CarrierConfigRepository {
+    override suspend fun startObservingCarrierConfigUpdates() {}
+
+    val configsById = mutableMapOf<Int, SystemUiCarrierConfig>()
+
+    override fun getOrCreateConfigForSubId(subId: Int): SystemUiCarrierConfig =
+        configsById.getOrPut(subId) { SystemUiCarrierConfig(subId, createDefaultTestConfig()) }
+}
+
+val CarrierConfigRepository.fake
+    get() = this as FakeCarrierConfigRepository
+
+fun createDefaultTestConfig() =
+    PersistableBundle().also {
+        it.putBoolean(
+            android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL,
+            false,
+        )
+        it.putBoolean(
+            android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL,
+            false,
+        )
+        it.putBoolean(android.telephony.CarrierConfigManager.KEY_SHOW_5G_SLICE_ICON_BOOL, true)
+    }
+
+/** Override the default config with the given (key, value) pair */
+fun configWithOverride(key: String, override: Boolean): PersistableBundle =
+    createDefaultTestConfig().also { it.putBoolean(key, override) }
+
+/** Override any number of configs from the default */
+fun configWithOverrides(vararg overrides: Pair<String, Boolean>) =
+    createDefaultTestConfig().also { config ->
+        overrides.forEach { (key, value) -> config.putBoolean(key, value) }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorKosmos.kt
similarity index 60%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorKosmos.kt
index 13fde96..7cb2750 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/CarrierConfigInteractorKosmos.kt
@@ -14,10 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.statusbar.disableflags.domain.interactor.disableFlagsInteractor
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.carrierConfigRepository
 
-val Kosmos.collapsedStatusBarInteractor: CollapsedStatusBarInteractor by
-    Kosmos.Fixture { CollapsedStatusBarInteractor(disableFlagsInteractor) }
+val Kosmos.carrierConfigInteractor by
+    Kosmos.Fixture {
+        CarrierConfigInteractor(
+            carrierConfigRepository,
+            mobileIconsInteractor,
+            applicationCoroutineScope,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
index 3a4bf8e..3b8adb4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/FakeMobileIconsInteractor.kt
@@ -55,10 +55,13 @@
 
     override val filteredSubscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
 
+    override val defaultDataSubId = MutableStateFlow(DEFAULT_DATA_SUB_ID)
+
     private val _activeDataConnectionHasDataEnabled = MutableStateFlow(false)
     override val activeDataConnectionHasDataEnabled = _activeDataConnectionHasDataEnabled
 
-    override val activeDataIconInteractor = MutableStateFlow(null)
+    override val activeDataIconInteractor: MutableStateFlow<MobileIconInteractor?> =
+        MutableStateFlow(null)
 
     override val alwaysShowDataRatIcon = MutableStateFlow(false)
 
@@ -83,13 +86,14 @@
 
     override val isDeviceInEmergencyCallsOnlyMode = MutableStateFlow(false)
 
-    /** Always returns a new fake interactor */
     override fun getMobileConnectionInteractorForSubId(subId: Int): FakeMobileIconInteractor {
-        return FakeMobileIconInteractor(tableLogBuffer).also {
-            interactorCache[subId] = it
-            // Also update the icons
-            icons.value = interactorCache.values.toList()
-        }
+        return interactorCache
+            .getOrElse(subId) { FakeMobileIconInteractor(tableLogBuffer) }
+            .also {
+                interactorCache[subId] = it
+                // Also update the icons
+                icons.value = interactorCache.values.toList()
+            }
     }
 
     /**
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstantsKosmos.kt
similarity index 62%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstantsKosmos.kt
index 580f617..3bdddf8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityConstantsKosmos.kt
@@ -14,9 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.statusbar.pipeline.shared
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.connectivityConstants by Kosmos.Fixture { FakeConnectivityConstnants() }
+
+class FakeConnectivityConstnants : ConnectivityConstants {
+    override var hasDataCapabilities: Boolean = true
+
+    override var shouldShowActivityConfig: Boolean = false
+}
+
+val ConnectivityConstants.fake
+    get() = this as FakeConnectivityConstnants
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorKosmos.kt
new file mode 100644
index 0000000..39fff0f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarIconBlockListInteractorKosmos.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import android.content.res.mainResources
+import android.provider.Settings
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testCase
+import com.android.systemui.res.R
+import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
+import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
+
+val Kosmos.homeStatusBarIconBlockListInteractor by
+    Kosmos.Fixture { HomeStatusBarIconBlockListInteractor(mainResources, secureSettingsRepository) }
+
+/**
+ * [icons] can be a list of icons that should appear on the blocklist. Note that this should be
+ * called before instantiating your class dependent on this list, since it overrides resources and
+ * is not reactive to resource changes.
+ */
+suspend fun Kosmos.setHomeStatusBarIconBlockList(icons: List<String>) {
+    var volBlocked = false
+    val otherIcons = mutableListOf<String>()
+    icons.forEach { icon ->
+        if (icon.lowercase() == "volume") {
+            volBlocked = true
+        } else {
+            otherIcons.add(icon)
+        }
+    }
+
+    fakeSecureSettingsRepository.setInt(
+        Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON,
+        if (volBlocked) 0 else 1,
+    )
+
+    testCase.overrideResource(
+        R.array.config_collapsed_statusbar_icon_blocklist,
+        otherIcons.toTypedArray(),
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorKosmos.kt
new file mode 100644
index 0000000..c1b6681
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/HomeStatusBarInteractorKosmos.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.pipeline.shared.domain.interactor
+
+import android.telephony.CarrierConfigManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.disableflags.domain.interactor.disableFlagsInteractor
+import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.airplaneModeInteractor
+import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.carrierConfigRepository
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.configWithOverride
+import com.android.systemui.statusbar.pipeline.mobile.data.repository.fake
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.carrierConfigInteractor
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.fakeMobileIconsInteractor
+
+val Kosmos.homeStatusBarInteractor: HomeStatusBarInteractor by
+    Kosmos.Fixture {
+        HomeStatusBarInteractor(
+            airplaneModeInteractor,
+            carrierConfigInteractor,
+            disableFlagsInteractor,
+        )
+    }
+
+/** Set the default data subId to 1, and sets the carrier config setting to [show] */
+fun Kosmos.setHomeStatusBarInteractorShowOperatorName(show: Boolean) {
+    fakeMobileIconsInteractor.defaultDataSubId.value = 1
+    carrierConfigRepository.fake.configsById[1] =
+        SystemUiCarrierConfig(
+            1,
+            configWithOverride(CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, show),
+        )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
index eb17237..924b6b4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/HomeStatusBarViewModelKosmos.kt
@@ -27,18 +27,23 @@
 import com.android.systemui.statusbar.events.domain.interactor.systemStatusEventAnimationInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
 import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
+import com.android.systemui.statusbar.phone.domain.interactor.darkIconInteractor
 import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
-import com.android.systemui.statusbar.pipeline.shared.domain.interactor.collapsedStatusBarInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.homeStatusBarIconBlockListInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.homeStatusBarInteractor
 
-val Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
+var Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
     Kosmos.Fixture {
         HomeStatusBarViewModelImpl(
-            collapsedStatusBarInteractor,
+            homeStatusBarInteractor,
+            homeStatusBarIconBlockListInteractor,
             lightsOutInteractor,
             activeNotificationsInteractor,
+            darkIconInteractor,
             headsUpNotificationInteractor,
             keyguardTransitionInteractor,
             keyguardInteractor,
+            statusBarOperatorNameViewModel,
             sceneInteractor,
             sceneContainerOcclusionInteractor,
             shadeInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelKosmos.kt
similarity index 69%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelKosmos.kt
index 580f617..5887e3c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/StatusBarOperatorNameViewModelKosmos.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.mobileIconsInteractor
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.statusBarOperatorNameViewModel by
+    Kosmos.Fixture { StatusBarOperatorNameViewModel(mobileIconsInteractor) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeCastController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeCastController.kt
index 2df0c7a5..da6b2ae 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeCastController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeCastController.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy
 
+import android.media.projection.StopReason
 import java.io.PrintWriter
 
 class FakeCastController : CastController {
@@ -45,7 +46,7 @@
 
     override fun startCasting(device: CastDevice?) {}
 
-    override fun stopCasting(device: CastDevice?) {
+    override fun stopCasting(device: CastDevice?, @StopReason stopReason: Int) {
         lastStoppedDevice = device
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
index 932e768..6c98d19 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.mainCoroutineContext
 import com.android.systemui.plugins.activityStarter
+import com.android.systemui.shade.data.repository.shadeDialogContextInteractor
 import com.android.systemui.statusbar.phone.systemUIDialogFactory
 import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.modesDialogViewModel
 import com.android.systemui.util.mockito.mock
@@ -35,5 +36,6 @@
             { modesDialogViewModel },
             modesDialogEventLogger,
             mainCoroutineContext,
+            shadeDialogContextInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.kt
index a357275..f31697e8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/settings/FakeSettings.kt
@@ -70,6 +70,14 @@
         }
     }
 
+    fun getContentObservers(uri: Uri, userHandle: Int): List<ContentObserver> {
+        if (userHandle == UserHandle.USER_ALL) {
+            return contentObserversAllUsers[uri.toString()] ?: listOf()
+        } else {
+            return contentObservers[SettingsKey(userHandle, uri.toString())] ?: listOf()
+        }
+    }
+
     override fun getContentResolver(): ContentResolver {
         throw UnsupportedOperationException("FakeSettings.getContentResolver is not implemented")
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckerCastController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckerCastController.java
index 2249bc0..857dc85 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckerCastController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckerCastController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.utils.leaks;
 
+import android.media.projection.StopReason;
 import android.testing.LeakCheck;
 
 import com.android.systemui.statusbar.policy.CastController;
@@ -51,7 +52,7 @@
     }
 
     @Override
-    public void stopCasting(CastDevice device) {
+    public void stopCasting(CastDevice device, @StopReason int stopReason) {
 
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
index 34661ce..4fda95b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/ui/viewmodel/VolumeDialogRingerDrawerViewModelKosmos.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyInteractor
+import com.android.systemui.statusbar.policy.configurationController
 import com.android.systemui.volume.dialog.domain.interactor.volumeDialogVisibilityInteractor
 import com.android.systemui.volume.dialog.ringer.domain.volumeDialogRingerInteractor
 import com.android.systemui.volume.dialog.shared.volumeDialogLogger
@@ -37,5 +38,6 @@
             vibrator = vibratorHelper,
             volumeDialogLogger = volumeDialogLogger,
             visibilityInteractor = volumeDialogVisibilityInteractor,
+            configurationController = configurationController,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractorKosmos.kt
index 423100a..44917dd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/sliders/domain/interactor/VolumeDialogSliderInteractorKosmos.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.volume.dialog.sliders.domain.interactor
 
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.plugins.volumeDialogController
 import com.android.systemui.volume.dialog.domain.interactor.volumeDialogStateInteractor
 import com.android.systemui.volume.dialog.sliders.domain.model.volumeDialogSliderType
@@ -25,6 +26,7 @@
     Kosmos.Fixture {
         VolumeDialogSliderInteractor(
             volumeDialogSliderType,
+            applicationCoroutineScope,
             volumeDialogStateInteractor,
             volumeDialogController,
         )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
similarity index 76%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
index 580f617..7281e03 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/data/repository/WindowRootViewBlurRepositoryKosmos.kt
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.window.data.repository
 
 import com.android.systemui.kosmos.Kosmos
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.windowRootViewBlurRepository by Kosmos.Fixture { WindowRootViewBlurRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
similarity index 60%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
index 580f617..ad30ea2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/promoted/PromotedNotificationsProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/domain/interactor/WindowRootViewBlurInteractorKosmos.kt
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.notification.promoted
+package com.android.systemui.window.domain.interactor
 
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.window.data.repository.windowRootViewBlurRepository
 
-var Kosmos.promotedNotificationsProvider: PromotedNotificationsProvider by
-    Kosmos.Fixture { PromotedNotificationsProviderImpl() }
+val Kosmos.windowRootViewBlurInteractor by
+    Kosmos.Fixture {
+        WindowRootViewBlurInteractor(
+            repository = windowRootViewBlurRepository,
+            keyguardInteractor = keyguardInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt
new file mode 100644
index 0000000..864048d
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/window/ui/viewmodel/WindowRootViewModelKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.window.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.transitions.FakeBouncerTransition
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
+import org.mockito.internal.util.collections.Sets
+
+val Kosmos.fakeBouncerTransitions by
+    Kosmos.Fixture<Set<FakeBouncerTransition>> {
+        Sets.newSet(FakeBouncerTransition(), FakeBouncerTransition())
+    }
+
+val Kosmos.windowRootViewModel by
+    Kosmos.Fixture { WindowRootViewModel(fakeBouncerTransitions, windowRootViewBlurInteractor) }
diff --git a/packages/Vcn/framework-b/src/android/net/vcn/VcnTransportInfo.java b/packages/Vcn/framework-b/src/android/net/vcn/VcnTransportInfo.java
index 3638429..a760b12 100644
--- a/packages/Vcn/framework-b/src/android/net/vcn/VcnTransportInfo.java
+++ b/packages/Vcn/framework-b/src/android/net/vcn/VcnTransportInfo.java
@@ -161,7 +161,14 @@
         return 0;
     }
 
-    /** @hide */
+    /**
+     * Create a copy of a {@link VcnTransportInfo} with some fields redacted based on the
+     * permissions held by the receiving app.
+     *
+     * @param redactions bitmask of redactions that needs to be performed on this instance.
+     * @return the copy of this instance with the necessary redactions.
+     * @hide
+     */
     @FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
     @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
     @Override
diff --git a/ravenwood/scripts/extract-last-soong-commands.py b/ravenwood/scripts/extract-last-soong-commands.py
index c08d4aa..0629b77 100755
--- a/ravenwood/scripts/extract-last-soong-commands.py
+++ b/ravenwood/scripts/extract-last-soong-commands.py
@@ -32,7 +32,7 @@
 HEADER = r'''#!/bin/bash
 
 set -e # Stop on a failed command
-
+set -x # Print command line before executing
 cd "${ANDROID_BUILD_TOP:?}"
 
 '''
@@ -65,16 +65,8 @@
                     command = m.groups()[0]
 
                     count += 1
-                    out.write(f'### Command {count} ========\n')
-
-                    # Show the full command line before executing it.
-                    out.write('#echo ' + shlex.quote(command) + '\n')
-                    out.write('\n')
-
-                    # Execute the command.
-                    out.write('#' + command + '\n')
-
-                    out.write('\n')
+                    out.write(f'### Command {count} ========\n\n')
+                    out.write('#' + command + '\n\n')
 
                     continue
 
diff --git a/ravenwood/texts/ravenwood-build.prop b/ravenwood/texts/ravenwood-build.prop
index 93a18cf..7cc4454 100644
--- a/ravenwood/texts/ravenwood-build.prop
+++ b/ravenwood/texts/ravenwood-build.prop
@@ -42,3 +42,4 @@
 ro.build.version.release_or_codename=$$$ro.build.version.release_or_codename
 ro.build.version.release_or_preview_display=$$$ro.build.version.release_or_preview_display
 ro.build.version.sdk=$$$ro.build.version.sdk
+ro.build.version.sdk_full=$$$ro.build.version.sdk_full
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 3441d94..9ceca5d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -1589,7 +1589,13 @@
      * lock because this calls out to WindowManagerService.
      */
     void addWindowTokensForAllDisplays() {
-        final Display[] displays = mDisplayManager.getDisplays();
+        Display[] displays = {};
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            displays = mDisplayManager.getDisplays();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
         for (int i = 0; i < displays.length; i++) {
             final int displayId = displays[i].getDisplayId();
             addWindowTokenForDisplay(displayId);
@@ -1625,7 +1631,13 @@
     }
 
     public void onRemoved() {
-        final Display[] displays = mDisplayManager.getDisplays();
+        Display[] displays = {};
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            displays = mDisplayManager.getDisplays();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
         for (int i = 0; i < displays.length; i++) {
             final int displayId = displays[i].getDisplayId();
             onDisplayRemoved(displayId);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 5133575..79888b0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -261,27 +261,27 @@
                             ? event.getDisplayId() : Display.DEFAULT_DISPLAY;
 
                     switch (gestureType) {
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN:
                                 mAms.getMagnificationController().scaleMagnificationByStep(
                                         displayId, MagnificationController.ZOOM_DIRECTION_IN);
                             return true;
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT:
                                 mAms.getMagnificationController().scaleMagnificationByStep(
                                         displayId, MagnificationController.ZOOM_DIRECTION_OUT);
                             return true;
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT:
                             mAms.getMagnificationController().panMagnificationByStep(
                                     displayId, MagnificationController.PAN_DIRECTION_LEFT);
                             return true;
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT:
                             mAms.getMagnificationController().panMagnificationByStep(
                                     displayId, MagnificationController.PAN_DIRECTION_RIGHT);
                             return true;
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP:
                             mAms.getMagnificationController().panMagnificationByStep(
                                     displayId, MagnificationController.PAN_DIRECTION_UP);
                             return true;
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN:
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN:
                             mAms.getMagnificationController().panMagnificationByStep(
                                     displayId, MagnificationController.PAN_DIRECTION_DOWN);
                             return true;
@@ -292,12 +292,12 @@
                 @Override
                 public boolean isKeyGestureSupported(int gestureType) {
                     return switch (gestureType) {
-                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN,
-                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT,
-                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT,
-                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT,
-                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP,
-                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN -> true;
+                        case KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN,
+                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT,
+                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT,
+                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT,
+                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP,
+                             KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN -> true;
                         default -> false;
                     };
                 }
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
index 669025f..37276dd 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionManagerServiceImpl.java
@@ -155,23 +155,8 @@
         int callingPid = Binder.getCallingPid();
 
         final SafeOneTimeExecuteAppFunctionCallback safeExecuteAppFunctionCallback =
-                new SafeOneTimeExecuteAppFunctionCallback(executeAppFunctionCallback,
-                        new SafeOneTimeExecuteAppFunctionCallback.CompletionCallback() {
-                            @Override
-                            public void finalizeOnSuccess(
-                                    @NonNull ExecuteAppFunctionResponse result,
-                                    long executionStartTimeMillis) {
-                                mLoggerWrapper.logAppFunctionSuccess(requestInternal, result,
-                                        callingUid, executionStartTimeMillis);
-                            }
-
-                            @Override
-                            public void finalizeOnError(@NonNull AppFunctionException error,
-                                    long executionStartTimeMillis) {
-                                mLoggerWrapper.logAppFunctionError(requestInternal,
-                                        error.getErrorCode(), callingUid, executionStartTimeMillis);
-                            }
-                        });
+                initializeSafeExecuteAppFunctionCallback(
+                        requestInternal, executeAppFunctionCallback, callingUid);
 
         String validatedCallingPackage;
         try {
@@ -576,6 +561,38 @@
         }
     }
 
+    /**
+     * Returns a new {@link SafeOneTimeExecuteAppFunctionCallback} initialized with a {@link
+     * SafeOneTimeExecuteAppFunctionCallback.CompletionCallback} that logs the results.
+     */
+    @VisibleForTesting
+    SafeOneTimeExecuteAppFunctionCallback initializeSafeExecuteAppFunctionCallback(
+            @NonNull ExecuteAppFunctionAidlRequest requestInternal,
+            @NonNull IExecuteAppFunctionCallback executeAppFunctionCallback,
+            int callingUid) {
+        return new SafeOneTimeExecuteAppFunctionCallback(
+                executeAppFunctionCallback,
+                new SafeOneTimeExecuteAppFunctionCallback.CompletionCallback() {
+                    @Override
+                    public void finalizeOnSuccess(
+                            @NonNull ExecuteAppFunctionResponse result,
+                            long executionStartTimeMillis) {
+                        mLoggerWrapper.logAppFunctionSuccess(
+                                requestInternal, result, callingUid, executionStartTimeMillis);
+                    }
+
+                    @Override
+                    public void finalizeOnError(
+                            @NonNull AppFunctionException error, long executionStartTimeMillis) {
+                        mLoggerWrapper.logAppFunctionError(
+                                requestInternal,
+                                error.getErrorCode(),
+                                callingUid,
+                                executionStartTimeMillis);
+                    }
+                });
+    }
+
     private static class AppFunctionMetadataObserver implements ObserverCallback {
         @Nullable private final MetadataSyncAdapter mPerUserMetadataSyncAdapter;
 
diff --git a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java
index 7ba1bbc..666d8fe 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/AppFunctionsLoggerWrapper.java
@@ -26,58 +26,99 @@
 import android.os.SystemClock;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Objects;
+import java.util.concurrent.Executor;
 
 /** Wraps AppFunctionsStatsLog. */
 public class AppFunctionsLoggerWrapper {
     private static final String TAG = AppFunctionsLoggerWrapper.class.getSimpleName();
 
-    private static final int SUCCESS_RESPONSE_CODE = -1;
+    @VisibleForTesting static final int SUCCESS_RESPONSE_CODE = -1;
 
-    private final Context mContext;
+    private final PackageManager mPackageManager;
+    private final Executor mLoggingExecutor;
+    private final AppFunctionsLoggerClock mLoggerClock;
 
-    public AppFunctionsLoggerWrapper(@NonNull Context context) {
-        mContext = Objects.requireNonNull(context);
+    AppFunctionsLoggerWrapper(@NonNull Context context) {
+        this(context.getPackageManager(), LOGGING_THREAD_EXECUTOR, SystemClock::elapsedRealtime);
     }
 
-    void logAppFunctionSuccess(ExecuteAppFunctionAidlRequest request,
-            ExecuteAppFunctionResponse response, int callingUid, long executionStartTimeMillis) {
-        logAppFunctionsRequestReported(request, SUCCESS_RESPONSE_CODE,
-                response.getResponseDataSize(), callingUid, executionStartTimeMillis);
+    @VisibleForTesting
+    AppFunctionsLoggerWrapper(
+            @NonNull PackageManager packageManager,
+            @NonNull Executor executor,
+            AppFunctionsLoggerClock loggerClock) {
+        mLoggingExecutor = Objects.requireNonNull(executor);
+        mPackageManager = Objects.requireNonNull(packageManager);
+        mLoggerClock = loggerClock;
     }
 
-    void logAppFunctionError(ExecuteAppFunctionAidlRequest request, int errorCode, int callingUid,
+    void logAppFunctionSuccess(
+            ExecuteAppFunctionAidlRequest request,
+            ExecuteAppFunctionResponse response,
+            int callingUid,
             long executionStartTimeMillis) {
-        logAppFunctionsRequestReported(request, errorCode, /* responseSizeBytes = */ 0, callingUid,
+        logAppFunctionsRequestReported(
+                request,
+                SUCCESS_RESPONSE_CODE,
+                response.getResponseDataSize(),
+                callingUid,
                 executionStartTimeMillis);
     }
 
-    private void logAppFunctionsRequestReported(ExecuteAppFunctionAidlRequest request,
-            int errorCode, int responseSizeBytes, int callingUid, long executionStartTimeMillis) {
+    void logAppFunctionError(
+            ExecuteAppFunctionAidlRequest request,
+            int errorCode,
+            int callingUid,
+            long executionStartTimeMillis) {
+        logAppFunctionsRequestReported(
+                request,
+                errorCode,
+                /* responseSizeBytes= */ 0,
+                callingUid,
+                executionStartTimeMillis);
+    }
+
+    private void logAppFunctionsRequestReported(
+            ExecuteAppFunctionAidlRequest request,
+            int errorCode,
+            int responseSizeBytes,
+            int callingUid,
+            long executionStartTimeMillis) {
         final long e2eRequestLatencyMillis =
-                SystemClock.elapsedRealtime() - request.getRequestTime();
+                mLoggerClock.getCurrentTimeMillis() - request.getRequestTime();
         final long requestOverheadMillis =
-                executionStartTimeMillis > 0 ? (executionStartTimeMillis - request.getRequestTime())
+                executionStartTimeMillis > 0
+                        ? (executionStartTimeMillis - request.getRequestTime())
                         : e2eRequestLatencyMillis;
-        LOGGING_THREAD_EXECUTOR.execute(() -> AppFunctionsStatsLog.write(
-                AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED,
-                /* callerPackageUid= */ callingUid,
-                /* targetPackageUid= */
-                getPackageUid(request.getClientRequest().getTargetPackageName()),
-                /* errorCode= */ errorCode,
-                /* requestSizeBytes= */ request.getClientRequest().getRequestDataSize(),
-                /* responseSizeBytes= */  responseSizeBytes,
-                /* requestDurationMs= */ e2eRequestLatencyMillis,
-                /* requestOverheadMs= */ requestOverheadMillis)
-        );
+        mLoggingExecutor.execute(
+                () ->
+                        AppFunctionsStatsLog.write(
+                                AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED,
+                                /* callerPackageUid= */ callingUid,
+                                /* targetPackageUid= */ getPackageUid(
+                                        request.getClientRequest().getTargetPackageName()),
+                                /* errorCode= */ errorCode,
+                                /* requestSizeBytes= */ request.getClientRequest()
+                                        .getRequestDataSize(),
+                                /* responseSizeBytes= */ responseSizeBytes,
+                                /* requestDurationMs= */ e2eRequestLatencyMillis,
+                                /* requestOverheadMs= */ requestOverheadMillis));
     }
 
     private int getPackageUid(String packageName) {
         try {
-            return mContext.getPackageManager().getPackageUid(packageName, 0);
+            return mPackageManager.getPackageUid(packageName, 0);
         } catch (PackageManager.NameNotFoundException e) {
             Slog.e(TAG, "Package uid not found for " + packageName);
         }
         return 0;
     }
+
+    /** Wraps a custom clock for easier testing. */
+    interface AppFunctionsLoggerClock {
+        long getCurrentTimeMillis();
+    }
 }
diff --git a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
index a5ae7e3..4cba8ec 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/RunAppFunctionServiceCallback.java
@@ -23,6 +23,7 @@
 import android.app.appfunctions.ICancellationCallback;
 import android.app.appfunctions.IExecuteAppFunctionCallback;
 import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback;
+import android.os.SystemClock;
 import android.util.Slog;
 
 import com.android.server.appfunctions.RemoteServiceCaller.RunServiceCallCallback;
@@ -52,7 +53,8 @@
             @NonNull IAppFunctionService service,
             @NonNull ServiceUsageCompleteListener serviceUsageCompleteListener) {
         try {
-            mSafeExecuteAppFunctionCallback.setExecutionStartTimeMillis();
+            mSafeExecuteAppFunctionCallback.setExecutionStartTimeAfterBindMillis(
+                    SystemClock.elapsedRealtime());
             service.executeAppFunction(
                     mRequestInternal.getClientRequest(),
                     mRequestInternal.getCallingPackage(),
@@ -73,8 +75,7 @@
         } catch (Exception e) {
             mSafeExecuteAppFunctionCallback.onError(
                     new AppFunctionException(
-                            AppFunctionException.ERROR_APP_UNKNOWN_ERROR,
-                            e.getMessage()));
+                            AppFunctionException.ERROR_APP_UNKNOWN_ERROR, e.getMessage()));
             serviceUsageCompleteListener.onCompleted();
         }
     }
@@ -83,7 +84,8 @@
     public void onFailedToConnect() {
         Slog.e(TAG, "Failed to connect to service");
         mSafeExecuteAppFunctionCallback.onError(
-                new AppFunctionException(AppFunctionException.ERROR_APP_UNKNOWN_ERROR,
+                new AppFunctionException(
+                        AppFunctionException.ERROR_APP_UNKNOWN_ERROR,
                         "Failed to connect to AppFunctionService"));
     }
 
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index 4bd987a..b753d01 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -72,6 +72,9 @@
     public static final String BACKUP_FINISHED_NOTIFICATION_RECEIVERS =
             "backup_finished_notification_receivers";
 
+    @VisibleForTesting
+    public static final String WAKELOCK_TIMEOUT_MILLIS = "wakelock_timeout_millis";
+
     // Hard coded default values.
     @VisibleForTesting
     public static final long DEFAULT_KEY_VALUE_BACKUP_INTERVAL_MILLISECONDS =
@@ -97,6 +100,9 @@
     @VisibleForTesting
     public static final String DEFAULT_BACKUP_FINISHED_NOTIFICATION_RECEIVERS = "";
 
+    @VisibleForTesting
+    public static final long DEFAULT_WAKELOCK_TIMEOUT_MILLIS = 30 * 60 * 1000; // 30 minutes
+
     // Backup manager constants.
     private long mKeyValueBackupIntervalMilliseconds;
     private long mKeyValueBackupFuzzMilliseconds;
@@ -106,6 +112,7 @@
     private boolean mFullBackupRequireCharging;
     private int mFullBackupRequiredNetworkType;
     private String[] mBackupFinishedNotificationReceivers;
+    private long mWakelockTimeoutMillis;
 
     public BackupManagerConstants(Handler handler, ContentResolver resolver) {
         super(handler, resolver, Settings.Secure.getUriFor(SETTING));
@@ -152,6 +159,8 @@
         } else {
             mBackupFinishedNotificationReceivers = backupFinishedNotificationReceivers.split(":");
         }
+        mWakelockTimeoutMillis = parser.getLong(WAKELOCK_TIMEOUT_MILLIS,
+                DEFAULT_WAKELOCK_TIMEOUT_MILLIS);
     }
 
     // The following are access methods for the individual parameters.
@@ -235,4 +244,9 @@
         }
         return mBackupFinishedNotificationReceivers;
     }
+
+    public synchronized long getWakelockTimeoutMillis() {
+        Slog.v(TAG, "wakelock timeout: " + mWakelockTimeoutMillis);
+        return mWakelockTimeoutMillis;
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 3025e2e..ac1f50f 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -181,11 +181,14 @@
     public static class BackupWakeLock {
         private final PowerManager.WakeLock mPowerManagerWakeLock;
         private boolean mHasQuit = false;
-        private int mUserId;
+        private final int mUserId;
+        private final BackupManagerConstants mBackupManagerConstants;
 
-        public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId) {
+        public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId,
+                BackupManagerConstants backupManagerConstants) {
             mPowerManagerWakeLock = powerManagerWakeLock;
             mUserId = userId;
+            mBackupManagerConstants = backupManagerConstants;
         }
 
         /** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */
@@ -199,7 +202,9 @@
                                         + mPowerManagerWakeLock.getTag()));
                 return;
             }
-            mPowerManagerWakeLock.acquire();
+            // Set a timeout for the wakelock. Otherwise if we fail internally and never call
+            // release(), the device might stay awake and drain battery indefinitely.
+            mPowerManagerWakeLock.acquire(mBackupManagerConstants.getWakelockTimeoutMillis());
             Slog.v(
                     TAG,
                     addUserIdToLogMessage(
@@ -217,6 +222,13 @@
                                         + mPowerManagerWakeLock.getTag()));
                 return;
             }
+
+            if (!mPowerManagerWakeLock.isHeld()) {
+                Slog.w(TAG, addUserIdToLogMessage(mUserId,
+                        "Wakelock not held: " + mPowerManagerWakeLock.getTag()));
+                return;
+            }
+
             mPowerManagerWakeLock.release();
             Slog.v(
                     TAG,
@@ -667,10 +679,8 @@
         mBackupPreferences = new UserBackupPreferences(mContext, mBaseStateDir);
 
         // Power management
-        mWakelock = new BackupWakeLock(
-                mPowerManager.newWakeLock(
-                        PowerManager.PARTIAL_WAKE_LOCK,
-                        "*backup*-" + userId + "-" + userBackupThread.getThreadId()), userId);
+        mWakelock = new BackupWakeLock(mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                "*backup*-" + userId + "-" + userBackupThread.getThreadId()), userId, mConstants);
 
         // Set up the various sorts of package tracking we do
         mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index a1d621d..6bf60bf 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -301,14 +301,19 @@
             // if the secure window is shown on a non-secure virtual display.
             DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
             Display display = displayManager.getDisplay(displayId);
-            if ((display.getFlags() & Display.FLAG_SECURE) == 0) {
-                showToastWhereUidIsRunning(activityInfo.applicationInfo.uid,
-                        com.android.internal.R.string.vdm_secure_window,
-                        Toast.LENGTH_LONG, mContext.getMainLooper());
+            if (display != null) {
+                if ((display.getFlags() & Display.FLAG_SECURE) == 0) {
+                    showToastWhereUidIsRunning(activityInfo.applicationInfo.uid,
+                            com.android.internal.R.string.vdm_secure_window,
+                            Toast.LENGTH_LONG, mContext.getMainLooper());
 
-                Counter.logIncrementWithUid(
-                        "virtual_devices.value_secure_window_blocked_count",
-                        mAttributionSource.getUid());
+                    Counter.logIncrementWithUid(
+                            "virtual_devices.value_secure_window_blocked_count",
+                            mAttributionSource.getUid());
+                }
+            } else {
+                Slog.e(TAG, "Calling onSecureWindowShown on a non existent/connected display: "
+                        + displayId);
             }
         }
 
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index fd18fa8..abfb826 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -55,6 +55,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
+import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -102,6 +103,7 @@
     private final PackageManagerInternal mPackageManager;
     private final WindowManagerInternal mWmInternal;
     private final DevicePolicyManagerInternal mDpmInternal;
+    private final AudioManager mAudioManager;
     private final Object mLock = new Object();
     private final AssistDataRequester mAssistDataRequester;
 
@@ -163,6 +165,8 @@
         mAtmInternal = Objects.requireNonNull(
                 LocalServices.getService(ActivityTaskManagerInternal.class));
         mPackageManager = LocalServices.getService(PackageManagerInternal.class);
+        mAudioManager = context.getSystemService(AudioManager.class);
+
         mWmInternal = Objects.requireNonNull(LocalServices.getService(WindowManagerInternal.class));
         mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
         mAssistDataRequester = new AssistDataRequester(
@@ -306,6 +310,10 @@
                 SystemClock.uptimeMillis());
         launchIntent.putExtra(ContextualSearchManager.EXTRA_ENTRYPOINT, entrypoint);
         launchIntent.putExtra(ContextualSearchManager.EXTRA_TOKEN, mToken);
+        if (Flags.includeAudioPlayingStatus()) {
+            launchIntent.putExtra(ContextualSearchManager.EXTRA_IS_AUDIO_PLAYING,
+                    mAudioManager.isMusicActive());
+        }
         boolean isAssistDataAllowed = mAtmInternal.isAssistDataAllowed();
         final List<ActivityAssistInfo> records = mAtmInternal.getTopVisibleActivities();
         final List<IBinder> activityTokens = new ArrayList<>(records.size());
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 06f9e2b..dc83064 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -229,7 +229,6 @@
         "power_hint_flags_lib",
         "biometrics_flags_lib",
         "am_flags_lib",
-        "updates_flags_lib",
         "com_android_server_accessibility_flags_lib",
         "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
         "com_android_launcher3_flags_lib",
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index bedc130..c1c03ff 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -18,6 +18,7 @@
 
 import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap;
 
+import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
 import static com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis;
 
 import android.app.ActivityManager;
@@ -232,7 +233,7 @@
     }
 
     @VisibleForTesting
-    GestureLauncherService(Context context, MetricsLogger metricsLogger,
+    public GestureLauncherService(Context context, MetricsLogger metricsLogger,
             QuickAccessWalletClient quickAccessWalletClient, UiEventLogger uiEventLogger) {
         super(context);
         mContext = context;
@@ -600,6 +601,45 @@
         return res;
     }
 
+    /**
+     * Processes a power key event in GestureLauncherService without performing an action. This
+     * method is called on every KEYCODE_POWER ACTION_DOWN event and ensures that, even if
+     * KEYCODE_POWER events are passed to and handled by the app, the GestureLauncherService still
+     * keeps track of all running KEYCODE_POWER events for its gesture detection and relevant
+     * actions.
+     */
+    public void processPowerKeyDown(KeyEvent event) {
+        if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0
+                && event.getEventTime() - mLastEmergencyGestureTriggered
+                < mEmergencyGesturePowerButtonCooldownPeriodMs) {
+            return;
+        }
+        if (event.isLongPress()) {
+            return;
+        }
+
+        final long powerTapInterval;
+
+        synchronized (this) {
+            powerTapInterval = event.getEventTime() - mLastPowerDown;
+            mLastPowerDown = event.getEventTime();
+            if (powerTapInterval >= POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) {
+                // Tap too slow, reset consecutive tap counts.
+                mFirstPowerDown = event.getEventTime();
+                mPowerButtonConsecutiveTaps = 1;
+                mPowerButtonSlowConsecutiveTaps = 1;
+            } else if (powerTapInterval >= POWER_DOUBLE_TAP_MAX_TIME_MS) {
+                // Tap too slow for shortcuts
+                mFirstPowerDown = event.getEventTime();
+                mPowerButtonConsecutiveTaps = 1;
+                mPowerButtonSlowConsecutiveTaps++;
+            } else if (!overridePowerKeyBehaviorInFocusedWindow() || powerTapInterval > 0) {
+                // Fast consecutive tap
+                mPowerButtonConsecutiveTaps++;
+                mPowerButtonSlowConsecutiveTaps++;
+            }
+        }
+    }
 
     /**
      * Attempts to intercept power key down event by detecting certain gesture patterns
@@ -648,7 +688,7 @@
                 mFirstPowerDown  = event.getEventTime();
                 mPowerButtonConsecutiveTaps = 1;
                 mPowerButtonSlowConsecutiveTaps++;
-            } else {
+            } else if (powerTapInterval > 0) {
                 // Fast consecutive tap
                 mPowerButtonConsecutiveTaps++;
                 mPowerButtonSlowConsecutiveTaps++;
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index c15cf34..6858e29 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -31,6 +31,7 @@
 per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
 per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS
 per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
+per-file GestureLauncherService.java = file:/INPUT_OWNERS
 per-file MmsServiceBroker.java = file:/telephony/OWNERS
 per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWNERS
 per-file PackageWatchdog.java = file:/services/core/java/com/android/server/crashrecovery/OWNERS
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 719928b..09440e0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -5266,6 +5266,22 @@
             }
         }
 
+        @Override
+        public void onNullBinding(ComponentName name) {
+            IAccountManagerResponse response = getResponseAndClose();
+            if (response != null) {
+                try {
+                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
+                            "disconnected");
+                } catch (RemoteException e) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "Session.onNullBinding: "
+                                + "caught RemoteException while responding", e);
+                    }
+                }
+            }
+        }
+
         public abstract void run() throws RemoteException;
 
         public void onTimedOut() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 4944caf..4b8770b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_HEALTH;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
@@ -31,6 +32,7 @@
 import static com.android.server.am.BroadcastConstants.getDeviceConfigBoolean;
 
 import android.annotation.NonNull;
+import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
 import android.app.ForegroundServiceTypePolicy;
 import android.content.ComponentName;
@@ -55,6 +57,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
 
 import dalvik.annotation.optimization.NeverCompile;
 
@@ -181,6 +184,12 @@
     static final String KEY_FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION =
             "follow_up_oomadj_update_wait_duration";
 
+    /*
+     * Oom score cutoff beyond which any process that does not have the CPU_TIME capability will be
+     * frozen.
+     */
+    static final String KEY_FREEZER_CUTOFF_ADJ = "freezer_cutoff_adj";
+
     private static final int DEFAULT_MAX_CACHED_PROCESSES = 1024;
     private static final boolean DEFAULT_PRIORITIZE_ALARM_BROADCASTS = true;
     private static final long DEFAULT_FGSERVICE_MIN_SHOWN_TIME = 2*1000;
@@ -267,6 +276,9 @@
      */
     private static final long DEFAULT_FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION = 1000L;
 
+    /** The default value to {@link #KEY_FREEZER_CUTOFF_ADJ} */
+    private static final int DEFAULT_FREEZER_CUTOFF_ADJ = ProcessList.CACHED_APP_MIN_ADJ;
+
     /**
      * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED}
      */
@@ -1171,6 +1183,14 @@
             DEFAULT_FOLLOW_UP_OOMADJ_UPDATE_WAIT_DURATION;
 
     /**
+     * The cutoff adj for the freezer, app processes with adj greater than this value will be
+     * eligible for the freezer.
+     *
+     * @see #KEY_FREEZER_CUTOFF_ADJ
+     */
+    public int FREEZER_CUTOFF_ADJ = DEFAULT_FREEZER_CUTOFF_ADJ;
+
+    /**
      * Indicates whether PSS profiling in AppProfiler is disabled or not.
      */
     static final String KEY_DISABLE_APP_PROFILER_PSS_PROFILING =
@@ -1194,6 +1214,7 @@
             new OnPropertiesChangedListener() {
                 @Override
                 public void onPropertiesChanged(Properties properties) {
+                    boolean oomAdjusterConfigUpdated = false;
                     for (String name : properties.getKeyset()) {
                         if (name == null) {
                             return;
@@ -1372,6 +1393,11 @@
                             case KEY_TIERED_CACHED_ADJ_UI_TIER_SIZE:
                                 updateUseTieredCachedAdj();
                                 break;
+                            case KEY_FREEZER_CUTOFF_ADJ:
+                                FREEZER_CUTOFF_ADJ = properties.getInt(KEY_FREEZER_CUTOFF_ADJ,
+                                        DEFAULT_FREEZER_CUTOFF_ADJ);
+                                oomAdjusterConfigUpdated = true;
+                                break;
                             case KEY_DISABLE_APP_PROFILER_PSS_PROFILING:
                                 updateDisableAppProfilerPssProfiling();
                                 break;
@@ -1389,6 +1415,13 @@
                                 break;
                         }
                     }
+                    if (oomAdjusterConfigUpdated) {
+                        final ActivityManagerInternal ami = LocalServices.getService(
+                                ActivityManagerInternal.class);
+                        if (ami != null) {
+                            ami.updateOomAdj(OOM_ADJ_REASON_RECONFIGURATION);
+                        }
+                    }
                 }
             };
 
@@ -2534,6 +2567,9 @@
         pw.print("  "); pw.print(KEY_ENABLE_NEW_OOMADJ);
         pw.print("="); pw.println(ENABLE_NEW_OOMADJ);
 
+        pw.print("  "); pw.print(KEY_FREEZER_CUTOFF_ADJ);
+        pw.print("="); pw.println(FREEZER_CUTOFF_ADJ);
+
         pw.print("  "); pw.print(KEY_DISABLE_APP_PROFILER_PSS_PROFILING);
         pw.print("="); pw.println(APP_PROFILER_PSS_PROFILING_DISABLED);
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cd929c1..50b6990 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4799,9 +4799,6 @@
             updateLruProcessLocked(app, false, null);
             checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
 
-            updateOomAdjLocked(app, OOM_ADJ_REASON_PROCESS_BEGIN);
-            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
-
             final long now = SystemClock.uptimeMillis();
             synchronized (mAppProfiler.mProfilerLock) {
                 app.mProfile.setLastRequestedGc(now);
@@ -4815,6 +4812,15 @@
             }
             mProcessesOnHold.remove(app);
 
+            // See if the top visible activity is waiting to run in this process...
+            if (com.android.server.am.Flags.expediteActivityLaunchOnColdStart()) {
+                if (normalMode) {
+                    mAtmInternal.attachApplication(app.getWindowProcessController());
+                }
+            }
+            updateOomAdjLocked(app, OOM_ADJ_REASON_PROCESS_BEGIN);
+            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
+
             if (!mConstants.mEnableWaitForFinishAttachApplication) {
                 finishAttachApplicationInner(startSeq, callingUid, pid);
             }
@@ -4880,18 +4886,21 @@
             // Mark the finish attach application phase as completed
             mProcessStateController.setPendingFinishAttach(app, false);
 
-            final boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
             final String processName = app.processName;
             boolean badApp = false;
             boolean didSomething = false;
 
-            // See if the top visible activity is waiting to run in this process...
-            if (normalMode) {
-                try {
-                    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
-                } catch (Exception e) {
-                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
-                    badApp = true;
+            if (!com.android.server.am.Flags.expediteActivityLaunchOnColdStart()) {
+                final boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
+
+                if (normalMode) {
+                    try {
+                        didSomething |= mAtmInternal.attachApplication(
+                                app.getWindowProcessController());
+                    } catch (Exception e) {
+                        Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
+                        badApp = true;
+                    }
                 }
             }
 
@@ -19387,9 +19396,6 @@
                     creatorPackage);
             if (creatorToken != null) {
                 extraIntent.setCreatorToken(creatorToken);
-                // TODO remove Slog.wtf once proven FrameworkStatsLog works. b/375396329
-                Slog.wtf(TAG, "A creator token is added to an intent. creatorPackage: "
-                        + creatorPackage + "; intent: " + extraIntent);
                 FrameworkStatsLog.write(INTENT_CREATOR_TOKEN_ADDED, creatorUid, false);
             }
         });
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 9a63546..cbebc90 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -449,6 +449,8 @@
                     return runSetAppZygotePreloadTimeout(pw);
                 case "set-media-foreground-service":
                     return runSetMediaForegroundService(pw);
+                case "clear-bad-process":
+                    return runClearBadProcess(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -4276,6 +4278,27 @@
         return 0;
     }
 
+    int runClearBadProcess(PrintWriter pw) throws RemoteException {
+        final String processName = getNextArgRequired();
+        int userId = UserHandle.USER_CURRENT;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            if ("--user".equals(opt)) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: unknown option " + opt);
+                return -1;
+            }
+        }
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = mInternal.getCurrentUserId();
+        }
+
+        pw.println("Clearing '" + processName + "' in u" + userId + " from bad processes list");
+        mInternal.mAppErrors.clearBadProcessForUser(processName, userId);
+        return 0;
+    }
+
     private Resources getResources(PrintWriter pw) throws RemoteException {
         // system resources does not contain all the device configuration, construct it manually.
         Configuration config = mInterface.getConfiguration();
@@ -4717,6 +4740,8 @@
             pw.println("  set-media-foreground-service inactive|active [--user USER_ID] <PACKAGE>"
                             + " <NOTIFICATION_ID>");
             pw.println("         Set an app's media service inactive or active.");
+            pw.println("  clear-bad-process [--user USER_ID] <PROCESS_NAME>");
+            pw.println("         Clears a process from the bad processes list.");
             Intent.printIntentArgsHelp(pw, "");
         }
     }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index b7a5f3e..2fbf05e 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -373,6 +373,24 @@
         }
     }
 
+    void clearBadProcessForUser(final String processName, final int userId) {
+        synchronized (mBadProcessLock) {
+            final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
+            badProcesses.putAll(mBadProcesses);
+            final SparseArray<BadProcessInfo> uids = badProcesses.get(processName);
+            if (uids == null) {
+                return;
+            }
+            for (int i = uids.size() - 1; i >= 0; --i) {
+                final int uid = uids.keyAt(i);
+                if (userId == UserHandle.USER_ALL || userId == UserHandle.getUserId(uid)) {
+                    badProcesses.remove(processName, uid);
+                }
+            }
+            mBadProcesses = badProcesses;
+        }
+    }
+
     void markBadProcess(final String processName, final int uid, BadProcessInfo info) {
         synchronized (mBadProcessLock) {
             final ProcessMap<BadProcessInfo> badProcesses = new ProcessMap<>();
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 2f5362f..d335529 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -25,9 +25,11 @@
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
+import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FOLLOW_UP;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_GET_PROVIDER;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END;
+import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE;
@@ -203,6 +205,10 @@
             FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_RESTRICTION_CHANGE;
     static final int UNFREEZE_REASON_COMPONENT_DISABLED =
             FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_COMPONENT_DISABLED;
+    static final int UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP =
+            FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_OOM_ADJ_FOLLOW_UP;
+    static final int UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION =
+            FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_OOM_ADJ_RECONFIGURATION;
 
     @IntDef(prefix = {"UNFREEZE_REASON_"}, value = {
         UNFREEZE_REASON_NONE,
@@ -234,6 +240,8 @@
         UNFREEZE_REASON_EXECUTING_SERVICE,
         UNFREEZE_REASON_RESTRICTION_CHANGE,
         UNFREEZE_REASON_COMPONENT_DISABLED,
+        UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP,
+        UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UnfreezeReason {}
@@ -2451,8 +2459,8 @@
                             synchronized (mAm.mPidsSelfLocked) {
                                 pr = mAm.mPidsSelfLocked.get(blocked);
                             }
-                            if (pr != null
-                                    && pr.mState.getCurAdj() < ProcessList.FREEZER_CUTOFF_ADJ) {
+                            if (pr != null && pr.mState.getCurAdj()
+                                    < mAm.mConstants.FREEZER_CUTOFF_ADJ) {
                                 Slog.d(TAG_AM, app.processName + " (" + pid + ") blocks "
                                         + pr.processName + " (" + blocked + ")");
                                 // Found at least one blocked non-cached process
@@ -2539,6 +2547,10 @@
                 return UNFREEZE_REASON_RESTRICTION_CHANGE;
             case OOM_ADJ_REASON_COMPONENT_DISABLED:
                 return UNFREEZE_REASON_COMPONENT_DISABLED;
+            case OOM_ADJ_REASON_FOLLOW_UP:
+                return UNFREEZE_REASON_OOM_ADJ_FOLLOW_UP;
+            case OOM_ADJ_REASON_RECONFIGURATION:
+                return UNFREEZE_REASON_OOM_ADJ_RECONFIGURATION;
             default:
                 return UNFREEZE_REASON_NONE;
         }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index aadf6f6..9c569db 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -55,6 +55,7 @@
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_NONE;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END;
+import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RECONFIGURATION;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK;
 import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE;
@@ -105,7 +106,6 @@
 import static com.android.server.am.ProcessList.CACHED_APP_MAX_ADJ;
 import static com.android.server.am.ProcessList.CACHED_APP_MIN_ADJ;
 import static com.android.server.am.ProcessList.FOREGROUND_APP_ADJ;
-import static com.android.server.am.ProcessList.FREEZER_CUTOFF_ADJ;
 import static com.android.server.am.ProcessList.HEAVY_WEIGHT_APP_ADJ;
 import static com.android.server.am.ProcessList.HOME_APP_ADJ;
 import static com.android.server.am.ProcessList.INVALID_ADJ;
@@ -232,6 +232,8 @@
                 return AppProtoEnums.OOM_ADJ_REASON_COMPONENT_DISABLED;
             case OOM_ADJ_REASON_FOLLOW_UP:
                 return AppProtoEnums.OOM_ADJ_REASON_FOLLOW_UP;
+            case OOM_ADJ_REASON_RECONFIGURATION:
+                return AppProtoEnums.OOM_ADJ_REASON_RECONFIGURATION;
             default:
                 return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
         }
@@ -288,6 +290,8 @@
                 return OOM_ADJ_REASON_METHOD + "_componentDisabled";
             case OOM_ADJ_REASON_FOLLOW_UP:
                 return OOM_ADJ_REASON_METHOD + "_followUp";
+            case OOM_ADJ_REASON_RECONFIGURATION:
+                return OOM_ADJ_REASON_METHOD + "_reconfiguration";
             default:
                 return "_unknown";
         }
@@ -4079,7 +4083,7 @@
         }
 
         // Reasons to freeze:
-        if (proc.mState.getCurAdj() >= FREEZER_CUTOFF_ADJ) {
+        if (proc.mState.getCurAdj() >= mConstants.FREEZER_CUTOFF_ADJ) {
             // Oomscore is in a high enough state, it is safe to freeze.
             return true;
         }
@@ -4098,9 +4102,8 @@
         final ProcessCachedOptimizerRecord opt = app.mOptRecord;
         final ProcessStateRecord state = app.mState;
         if (Flags.traceUpdateAppFreezeStateLsp()) {
-            final boolean oomAdjChanged =
-                    (state.getCurAdj() >= FREEZER_CUTOFF_ADJ ^ oldOomAdj >= FREEZER_CUTOFF_ADJ)
-                    || oldOomAdj == UNKNOWN_ADJ;
+            final boolean oomAdjChanged = (state.getCurAdj() >= mConstants.FREEZER_CUTOFF_ADJ
+                    ^ oldOomAdj >= mConstants.FREEZER_CUTOFF_ADJ) || oldOomAdj == UNKNOWN_ADJ;
             final boolean shouldNotFreezeChanged = opt.shouldNotFreezeAdjSeq() == mAdjSeq;
             final boolean hasCpuCapability =
                     (PROCESS_CAPABILITY_CPU_TIME & app.mState.getCurCapability())
diff --git a/services/core/java/com/android/server/am/PhantomProcessList.java b/services/core/java/com/android/server/am/PhantomProcessList.java
index 123780f..99bdd10 100644
--- a/services/core/java/com/android/server/am/PhantomProcessList.java
+++ b/services/core/java/com/android/server/am/PhantomProcessList.java
@@ -112,23 +112,10 @@
     private final ActivityManagerService mService;
     private final Handler mKillHandler;
 
-    private static final int CGROUP_V1 = 0;
-    private static final int CGROUP_V2 = 1;
-    private static final String[] CGROUP_PATH_PREFIXES = {
-        "/acct/uid_" /* cgroup v1 */,
-        "/sys/fs/cgroup/uid_" /* cgroup v2 */
-    };
-    private static final String CGROUP_PID_PREFIX = "/pid_";
-    private static final String CGROUP_PROCS = "/cgroup.procs";
-
-    @VisibleForTesting
-    int mCgroupVersion = CGROUP_V1;
-
     PhantomProcessList(final ActivityManagerService service) {
         mService = service;
         mKillHandler = service.mProcessList.sKillHandler;
         mInjector = new Injector();
-        probeCgroupVersion();
     }
 
     @VisibleForTesting
@@ -157,9 +144,15 @@
         final int appPid = app.getPid();
         InputStream input = mCgroupProcsFds.get(appPid);
         if (input == null) {
-            final String path = getCgroupFilePath(app.info.uid, appPid);
+            String path = null;
             try {
+                path = getCgroupFilePath(app.info.uid, appPid);
                 input = mInjector.openCgroupProcs(path);
+            } catch (IllegalArgumentException e) {
+                if (DEBUG_PROCESSES) {
+                    Slog.w(TAG, "Unable to obtain cgroup.procs path ", e);
+                }
+                return;
             } catch (FileNotFoundException | SecurityException e) {
                 if (DEBUG_PROCESSES) {
                     Slog.w(TAG, "Unable to open " + path, e);
@@ -207,18 +200,9 @@
         }
     }
 
-    private void probeCgroupVersion() {
-        for (int i = CGROUP_PATH_PREFIXES.length - 1; i >= 0; i--) {
-            if ((new File(CGROUP_PATH_PREFIXES[i] + Process.SYSTEM_UID)).exists()) {
-                mCgroupVersion = i;
-                break;
-            }
-        }
-    }
-
     @VisibleForTesting
     String getCgroupFilePath(int uid, int pid) {
-        return CGROUP_PATH_PREFIXES[mCgroupVersion] + uid + CGROUP_PID_PREFIX + pid + CGROUP_PROCS;
+        return nativeGetCgroupProcsPath(uid, pid);
     }
 
     static String getProcessName(int pid) {
@@ -630,4 +614,7 @@
             return PhantomProcessList.getProcessName(pid);
         }
     }
+
+    private static native String nativeGetCgroupProcsPath(int uid, int pid)
+            throws IllegalArgumentException;
 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 70febcd..bddde9d 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -383,12 +383,6 @@
     private static final long LMKD_RECONNECT_DELAY_MS = 1000;
 
     /**
-     * The cuttoff adj for the freezer, app processes with adj greater than this value will be
-     * eligible for the freezer.
-     */
-    static final int FREEZER_CUTOFF_ADJ = CACHED_APP_MIN_ADJ;
-
-    /**
      * Apps have no access to the private data directories of any other app, even if the other
      * app has made them world-readable.
      */
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 98f738c..49149e1 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1699,7 +1699,7 @@
         return mService.mOomAdjuster.mCachedAppOptimizer.useFreezer()
                 && !mOptRecord.isFreezeExempt()
                 && !mOptRecord.shouldNotFreeze()
-                && mState.getCurAdj() >= ProcessList.FREEZER_CUTOFF_ADJ;
+                && mState.getCurAdj() >= mService.mConstants.FREEZER_CUTOFF_ADJ;
     }
 
     public void forEachConnectionHost(Consumer<ProcessRecord> consumer) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 87f87c7..c82933c 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -158,6 +158,7 @@
         "aoc",
         "app_widgets",
         "arc_next",
+        "art_cloud",
         "art_mainline",
         "art_performance",
         "attack_tools",
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 89e4a8d..cfcede8 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -288,3 +288,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "expedite_activity_launch_on_cold_start"
+    namespace: "system_performance"
+    description: "Notify ActivityTaskManager of cold starts early to fix app launch behavior."
+    bug: "319519089"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 06c586f..295e044 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3191,7 +3191,7 @@
                     resolveProxyPackageName, proxyAttributionTag, proxyVirtualDeviceId,
                     Process.INVALID_UID, null, null,
                     Context.DEVICE_ID_DEFAULT, proxyFlags, !isProxyTrusted,
-                    "proxy " + message, shouldCollectMessage);
+                    "proxy " + message, shouldCollectMessage, 1);
             if (proxyReturn.getOpMode() != AppOpsManager.MODE_ALLOWED) {
                 return new SyncNotedAppOp(proxyReturn.getOpMode(), code, proxiedAttributionTag,
                         proxiedPackageName);
@@ -3210,7 +3210,20 @@
         return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
                 proxiedAttributionTag, proxiedVirtualDeviceId, proxyUid, resolveProxyPackageName,
                 proxyAttributionTag, proxyVirtualDeviceId, proxiedFlags, shouldCollectAsyncNotedOp,
-                message, shouldCollectMessage);
+                message, shouldCollectMessage, 1);
+    }
+
+    @Override
+    public void noteOperationsInBatch(Map batchedNoteOps) {
+        for (var entry : ((Map<AppOpsManager.NotedOp, Integer>) batchedNoteOps).entrySet()) {
+            AppOpsManager.NotedOp notedOp = entry.getKey();
+            int notedCount = entry.getValue();
+            mCheckOpsDelegateDispatcher.noteOperation(
+                    notedOp.getOp(), notedOp.getUid(), notedOp.getPackageName(),
+                    notedOp.getAttributionTag(), notedOp.getVirtualDeviceId(),
+                    notedOp.getShouldCollectAsyncNotedOp(), notedOp.getMessage(),
+                    notedOp.getShouldCollectMessage(), notedCount);
+        }
     }
 
     @Override
@@ -3228,7 +3241,7 @@
         }
         return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName,
                 attributionTag, Context.DEVICE_ID_DEFAULT, shouldCollectAsyncNotedOp, message,
-                shouldCollectMessage);
+                shouldCollectMessage, 1);
     }
 
     @Override
@@ -3237,13 +3250,12 @@
             String message, boolean shouldCollectMessage) {
         return mCheckOpsDelegateDispatcher.noteOperation(code, uid, packageName,
                 attributionTag, virtualDeviceId, shouldCollectAsyncNotedOp, message,
-                shouldCollectMessage);
+                shouldCollectMessage, 1);
     }
 
     private SyncNotedAppOp noteOperationImpl(int code, int uid, @Nullable String packageName,
-             @Nullable String attributionTag, int virtualDeviceId,
-             boolean shouldCollectAsyncNotedOp, @Nullable String message,
-             boolean shouldCollectMessage) {
+            @Nullable String attributionTag, int virtualDeviceId, boolean shouldCollectAsyncNotedOp,
+            @Nullable String message, boolean shouldCollectMessage, int notedCount) {
         String resolvedPackageName;
         if (!shouldUseNewCheckOp()) {
             verifyIncomingUid(uid);
@@ -3278,14 +3290,14 @@
         return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
                 virtualDeviceId, Process.INVALID_UID, null, null,
                 Context.DEVICE_ID_DEFAULT, AppOpsManager.OP_FLAG_SELF, shouldCollectAsyncNotedOp,
-                message, shouldCollectMessage);
+                message, shouldCollectMessage, notedCount);
     }
 
     private SyncNotedAppOp noteOperationUnchecked(int code, int uid, @NonNull String packageName,
             @Nullable String attributionTag, int virtualDeviceId, int proxyUid,
             String proxyPackageName, @Nullable String proxyAttributionTag, int proxyVirtualDeviceId,
             @OpFlags int flags, boolean shouldCollectAsyncNotedOp, @Nullable String message,
-            boolean shouldCollectMessage) {
+            boolean shouldCollectMessage, int notedCount) {
         PackageVerificationResult pvr;
         try {
             pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
@@ -3388,11 +3400,11 @@
                     virtualDeviceId, flags, AppOpsManager.MODE_ALLOWED);
 
             attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag,
-                    getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags);
+                    getPersistentId(proxyVirtualDeviceId), uidState.getState(), flags, notedCount);
 
             if (shouldCollectAsyncNotedOp) {
                 collectAsyncNotedOp(uid, packageName, code, attributionTag, flags, message,
-                        shouldCollectMessage);
+                        shouldCollectMessage, notedCount);
             }
 
             return new SyncNotedAppOp(AppOpsManager.MODE_ALLOWED, code, attributionTag,
@@ -3551,7 +3563,7 @@
      */
     private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode,
             @Nullable String attributionTag, @OpFlags int flags, @NonNull String message,
-            boolean shouldCollectMessage) {
+            boolean shouldCollectMessage, int notedCount) {
         Objects.requireNonNull(message);
 
         int callingUid = Binder.getCallingUid();
@@ -3559,42 +3571,51 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
-                Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
-
-                RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
-                AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
-                        attributionTag, message, System.currentTimeMillis());
-                final boolean[] wasNoteForwarded = {false};
-
                 if ((flags & (OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED)) != 0
                         && shouldCollectMessage) {
                     reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode,
                             attributionTag, message);
                 }
 
-                if (callbacks != null) {
+                Pair<String, Integer> key = getAsyncNotedOpsKey(packageName, uid);
+                RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
+                if (callbacks == null) {
+                    return;
+                }
+
+                final boolean[] wasNoteForwarded = {false};
+                if (Flags.rateLimitBatchedNoteOpAsyncCallbacksEnabled()) {
+                    notedCount = 1;
+                }
+
+                for (int i = 0; i < notedCount; i++) {
+                    AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
+                            attributionTag, message, System.currentTimeMillis());
+                    wasNoteForwarded[0] = false;
                     callbacks.broadcast((cb) -> {
                         try {
                             cb.opNoted(asyncNotedOp);
                             wasNoteForwarded[0] = true;
                         } catch (RemoteException e) {
                             Slog.e(TAG,
-                                    "Could not forward noteOp of " + opCode + " to " + packageName
+                                    "Could not forward noteOp of " + opCode + " to "
+                                            + packageName
                                             + "/" + uid + "(" + attributionTag + ")", e);
                         }
                     });
-                }
 
-                if (!wasNoteForwarded[0]) {
-                    ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get(key);
-                    if (unforwardedOps == null) {
-                        unforwardedOps = new ArrayList<>(1);
-                        mUnforwardedAsyncNotedOps.put(key, unforwardedOps);
-                    }
+                    if (!wasNoteForwarded[0]) {
+                        ArrayList<AsyncNotedAppOp> unforwardedOps = mUnforwardedAsyncNotedOps.get(
+                                key);
+                        if (unforwardedOps == null) {
+                            unforwardedOps = new ArrayList<>(1);
+                            mUnforwardedAsyncNotedOps.put(key, unforwardedOps);
+                        }
 
-                    unforwardedOps.add(asyncNotedOp);
-                    if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) {
-                        unforwardedOps.remove(0);
+                        unforwardedOps.add(asyncNotedOp);
+                        if (unforwardedOps.size() > MAX_UNFORWARDED_OPS) {
+                            unforwardedOps.remove(0);
+                        }
                     }
                 }
             }
@@ -4026,7 +4047,7 @@
 
         if (shouldCollectAsyncNotedOp && !isRestricted) {
             collectAsyncNotedOp(uid, packageName, code, attributionTag, AppOpsManager.OP_FLAG_SELF,
-                    message, shouldCollectMessage);
+                    message, shouldCollectMessage, 1);
         }
 
         return new SyncNotedAppOp(isRestricted ? MODE_IGNORED : MODE_ALLOWED, code, attributionTag,
@@ -7574,34 +7595,36 @@
 
         public SyncNotedAppOp noteOperation(int code, int uid, String packageName,
                 String attributionTag, int virtualDeviceId, boolean shouldCollectAsyncNotedOp,
-                String message, boolean shouldCollectMessage) {
+                String message, boolean shouldCollectMessage, int notedCount) {
             if (mPolicy != null) {
                 if (mCheckOpsDelegate != null) {
                     return mPolicy.noteOperation(code, uid, packageName, attributionTag,
                             virtualDeviceId, shouldCollectAsyncNotedOp, message,
-                            shouldCollectMessage, this::noteDelegateOperationImpl
+                            shouldCollectMessage, notedCount, this::noteDelegateOperationImpl
                     );
                 } else {
                     return mPolicy.noteOperation(code, uid, packageName, attributionTag,
                             virtualDeviceId, shouldCollectAsyncNotedOp, message,
-                            shouldCollectMessage, AppOpsService.this::noteOperationImpl
+                            shouldCollectMessage, notedCount, AppOpsService.this::noteOperationImpl
                     );
                 }
             } else if (mCheckOpsDelegate != null) {
                 return noteDelegateOperationImpl(code, uid, packageName, attributionTag,
-                        virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                        virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                        notedCount);
             }
             return noteOperationImpl(code, uid, packageName, attributionTag,
-                    virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                    virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+                    notedCount);
         }
 
         private SyncNotedAppOp noteDelegateOperationImpl(int code, int uid,
                 @Nullable String packageName, @Nullable String featureId, int virtualDeviceId,
                 boolean shouldCollectAsyncNotedOp, @Nullable String message,
-                boolean shouldCollectMessage) {
+                boolean shouldCollectMessage, int notedCount) {
             return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId,
                     virtualDeviceId, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
-                    AppOpsService.this::noteOperationImpl
+                    notedCount, AppOpsService.this::noteOperationImpl
             );
         }
 
diff --git a/services/core/java/com/android/server/appop/AttributedOp.java b/services/core/java/com/android/server/appop/AttributedOp.java
index 314664b..4d114b4 100644
--- a/services/core/java/com/android/server/appop/AttributedOp.java
+++ b/services/core/java/com/android/server/appop/AttributedOp.java
@@ -100,10 +100,12 @@
      * @param proxyDeviceId       The device Id of the proxy
      * @param uidState            UID state of the app noteOp/startOp was called for
      * @param flags               OpFlags of the call
+     * @param accessCount         The number of times the op is accessed
      */
     public void accessed(int proxyUid, @Nullable String proxyPackageName,
             @Nullable String proxyAttributionTag, @Nullable String proxyDeviceId,
-            @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags) {
+            @AppOpsManager.UidState int uidState, @AppOpsManager.OpFlags int flags,
+            int accessCount) {
         long accessTime = System.currentTimeMillis();
         accessed(accessTime, -1, proxyUid, proxyPackageName, proxyAttributionTag, proxyDeviceId,
                 uidState, flags);
@@ -111,7 +113,7 @@
         mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                 parent.packageName, persistentDeviceId, tag, uidState, flags, accessTime,
                 AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE,
-                DiscreteRegistry.ACCESS_TYPE_NOTE_OP);
+                DiscreteRegistry.ACCESS_TYPE_NOTE_OP, accessCount);
     }
 
     /**
@@ -255,7 +257,7 @@
         if (isStarted) {
             mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                     parent.packageName, persistentDeviceId, tag, uidState, flags, startTime,
-                    attributionFlags, attributionChainId, DiscreteRegistry.ACCESS_TYPE_START_OP);
+                    attributionFlags, attributionChainId, DiscreteRegistry.ACCESS_TYPE_START_OP, 1);
         }
     }
 
@@ -451,7 +453,7 @@
             mAppOpsService.mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid,
                     parent.packageName, persistentDeviceId, tag, event.getUidState(),
                     event.getFlags(), startTime, event.getAttributionFlags(),
-                    event.getAttributionChainId(), DiscreteRegistry.ACCESS_TYPE_RESUME_OP);
+                    event.getAttributionChainId(), DiscreteRegistry.ACCESS_TYPE_RESUME_OP, 1);
             if (shouldSendActive) {
                 mAppOpsService.scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
                         parent.packageName, tag, event.getVirtualDeviceId(), true,
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 6b02538..5e67f26 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -475,7 +475,7 @@
             @NonNull String deviceId, @Nullable String attributionTag, @UidState int uidState,
             @OpFlags int flags, long accessTime,
             @AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId,
-            @DiscreteRegistry.AccessType int accessType) {
+            @DiscreteRegistry.AccessType int accessType, int accessCount) {
         synchronized (mInMemoryLock) {
             if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
                 if (!isPersistenceInitializedMLocked()) {
@@ -484,7 +484,7 @@
                 }
                 getUpdatedPendingHistoricalOpsMLocked(
                         System.currentTimeMillis()).increaseAccessCount(op, uid, packageName,
-                        attributionTag, uidState, flags, 1);
+                        attributionTag, uidState, flags, accessCount);
 
                 mDiscreteRegistry.recordDiscreteAccess(uid, packageName, deviceId, op,
                         attributionTag, flags, uidState, accessTime, -1, attributionFlags,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index a3b20b9..4ec8138 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -635,7 +635,8 @@
         client.setPlaybackActive(mAudioService.isPlaybackActiveForUid(client.getUid()));
         client.setRecordingActive(mAudioService.isRecordingActiveForUid(client.getUid()));
         if (wasActive != client.isActive()) {
-            postUpdateCommunicationRouteClient(bluetoothScoRequestOwnerAttributionSource(),
+            postUpdateCommunicationRouteClient(wasActive ?
+                    client.getAttributionSource() : null,
                     "updateCommunicationRouteClientState");
         }
     }
diff --git a/services/core/java/com/android/server/audio/FadeOutManager.java b/services/core/java/com/android/server/audio/FadeOutManager.java
index 4d5bce5..fedfe51 100644
--- a/services/core/java/com/android/server/audio/FadeOutManager.java
+++ b/services/core/java/com/android/server/audio/FadeOutManager.java
@@ -199,7 +199,9 @@
             for (AudioPlaybackConfiguration apc : players) {
                 final VolumeShaper.Configuration volShaper =
                         mFadeConfigurations.getFadeOutVolumeShaperConfig(apc.getAudioAttributes());
-                fa.addFade(apc, /* skipRamp= */ false, volShaper);
+                if (volShaper != null) {
+                    fa.addFade(apc, /* skipRamp= */ false, volShaper);
+                }
             }
         }
     }
@@ -249,7 +251,7 @@
             final VolumeShaper.Configuration volShaper =
                     mFadeConfigurations.getFadeOutVolumeShaperConfig(apc.getAudioAttributes());
             final FadedOutApp fa = mUidToFadedAppsMap.get(apc.getClientUid());
-            if (fa == null) {
+            if (fa == null || volShaper == null) {
                 return;
             }
             fa.addFade(apc, /* skipRamp= */ true, volShaper);
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index 50d6508..0f0c900 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -17,7 +17,6 @@
 package com.android.server.display;
 
 import android.annotation.Nullable;
-import android.hardware.display.BrightnessInfo;
 import android.os.Handler;
 import android.os.IBinder;
 
@@ -60,7 +59,7 @@
         mModeChangeCallback = modeChangeCallback;
         mHdrClamper = hdrClamper;
         mNormalBrightnessModeController = normalBrightnessModeController;
-        mUseHdrClamper = flags.isHdrClamperEnabled() && !flags.useNewHdrBrightnessModifier();
+        mUseHdrClamper = !flags.useNewHdrBrightnessModifier();
         mNormalBrightnessModeController.resetNbmData(
                 displayDeviceConfig.getLuxThrottlingData());
         if (flags.useNewHdrBrightnessModifier()) {
@@ -121,8 +120,11 @@
     }
 
     void onBrightnessChanged(float brightness, float unthrottledBrightness,
-            @BrightnessInfo.BrightnessMaxReason int throttlingReason) {
-        mHbmController.onBrightnessChanged(brightness, unthrottledBrightness, throttlingReason);
+            DisplayBrightnessState state) {
+        mHbmController.onHdrBoostApplied(
+                state.getHdrBrightness() != DisplayBrightnessState.BRIGHTNESS_NOT_SET);
+        mHbmController.onBrightnessChanged(brightness, unthrottledBrightness,
+                state.getBrightnessMaxReason());
     }
 
     float getCurrentBrightnessMin() {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index bad5b8b..c8192e5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -21,8 +21,11 @@
 import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
 import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT;
 import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT;
+import static android.Manifest.permission.CONFIGURE_WIFI_DISPLAY;
+import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_DISPLAYS;
+import static android.Manifest.permission.MODIFY_HDR_CONVERSION_MODE;
 import static android.Manifest.permission.RESTRICT_DISPLAY_MODES;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
@@ -119,6 +122,7 @@
 import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
+import android.os.IBinder.FrozenStateChangeCallback;
 import android.os.IThermalService;
 import android.os.Looper;
 import android.os.Message;
@@ -272,6 +276,7 @@
     private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
     private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
     private static final int MSG_RECEIVED_DEVICE_STATE = 9;
+    private static final int MSG_DISPATCH_PENDING_PROCESS_EVENTS = 10;
     private static final int[] EMPTY_ARRAY = new int[0];
     private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode(
             HDR_CONVERSION_UNSUPPORTED);
@@ -286,7 +291,6 @@
     private InputManagerInternal mInputManagerInternal;
     private ActivityManagerInternal mActivityManagerInternal;
     private final UidImportanceListener mUidImportanceListener = new UidImportanceListener();
-    private final DisplayFrozenProcessListener mDisplayFrozenProcessListener;
 
     @Nullable
     private IMediaProjectionManager mProjectionService;
@@ -630,7 +634,6 @@
         mFlags = injector.getFlags();
         mHandler = new DisplayManagerHandler(displayThreadLooper);
         mHandlerExecutor = new HandlerExecutor(mHandler);
-        mDisplayFrozenProcessListener = new DisplayFrozenProcessListener();
         mUiHandler = UiThread.getHandler();
         mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
         mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
@@ -1165,31 +1168,11 @@
         }
     }
 
-    private class DisplayFrozenProcessListener
-            implements ActivityManagerInternal.FrozenProcessListener {
-        public void onProcessFrozen(int pid) {
-            synchronized (mSyncRoot) {
-                CallbackRecord callback = mCallbacks.get(pid);
-                if (callback == null) {
-                    return;
-                }
-                callback.setFrozen(true);
-            }
-        }
-
-        public void onProcessUnfrozen(int pid) {
-            // First, see if there is a callback associated with this pid.  If there's no
-            // callback, then there is nothing to do.
-            CallbackRecord callback;
-            synchronized (mSyncRoot) {
-                callback = mCallbacks.get(pid);
-                if (callback == null) {
-                    return;
-                }
-                callback.setFrozen(false);
-            }
-            // Attempt to dispatch pending events if the process is coming out of frozen.
+    private void dispatchPendingProcessEvents(@NonNull Object cb) {
+        if (cb instanceof CallbackRecord callback) {
             callback.dispatchPending();
+        } else {
+            Slog.wtf(TAG, "not a callback: " + cb);
         }
     }
 
@@ -2397,9 +2380,13 @@
         // We don't bother invalidating the display info caches here because any changes to the
         // display info will trigger a cache invalidation inside of LogicalDisplay before we hit
         // this point.
-        sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+        sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
 
         applyDisplayChangedLocked(display);
+
+        if (mDisplayTopologyCoordinator != null) {
+            mDisplayTopologyCoordinator.onDisplayChanged(display.getDisplayInfoLocked());
+        }
     }
 
     private void applyDisplayChangedLocked(@NonNull LogicalDisplay display) {
@@ -2643,7 +2630,8 @@
 
     private void updateCanHostTasksIfNeededLocked(LogicalDisplay display) {
         if (display.setCanHostTasksLocked(!mMirrorBuiltInDisplay)) {
-            sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+            sendDisplayEventIfEnabledLocked(display,
+                    DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
         }
     }
 
@@ -3474,7 +3462,7 @@
 
     private void sendDisplayEventFrameRateOverrideLocked(int displayId) {
         Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE,
-                displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
+                displayId, DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
         mHandler.sendMessage(msg);
     }
 
@@ -4047,6 +4035,9 @@
                     deliverDisplayGroupEvent(msg.arg1, msg.arg2);
                     break;
 
+                case MSG_DISPATCH_PENDING_PROCESS_EVENTS:
+                    dispatchPendingProcessEvents(msg.obj);
+                    break;
             }
         }
     }
@@ -4061,7 +4052,7 @@
                     handleLogicalDisplayAddedLocked(display);
                     break;
 
-                case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED:
+                case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_BASIC_CHANGED:
                     handleLogicalDisplayChangedLocked(display);
                     break;
 
@@ -4114,7 +4105,7 @@
         }
     }
 
-    private final class CallbackRecord implements DeathRecipient {
+    private final class CallbackRecord implements DeathRecipient, FrozenStateChangeCallback {
         public final int mPid;
         public final int mUid;
         private final IDisplayManagerCallback mCallback;
@@ -4137,6 +4128,8 @@
         private boolean mCached;
         @GuardedBy("mCallback")
         private boolean mFrozen;
+        @GuardedBy("mCallback")
+        private boolean mAlive;
 
         CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback,
                 @InternalEventFlag long internalEventFlagsMask) {
@@ -4146,18 +4139,20 @@
             mInternalEventFlagsMask = new AtomicLong(internalEventFlagsMask);
             mCached = false;
             mFrozen = false;
+            mAlive = true;
 
             if (deferDisplayEventsWhenFrozen()) {
-                // Some CallbackRecords are registered very early in system boot, before
-                // mActivityManagerInternal is initialized. If mActivityManagerInternal is null,
-                // do not register the frozen process listener.  However, do verify that all such
-                // registrations are for the self pid (which can never be frozen, so the frozen
-                // process listener does not matter).
-                if (mActivityManagerInternal != null) {
-                    mActivityManagerInternal.addFrozenProcessListener(pid, mHandlerExecutor,
-                            mDisplayFrozenProcessListener);
-                } else if (Process.myPid() != pid) {
-                    Slog.e(TAG, "DisplayListener registered too early");
+                try {
+                    callback.asBinder().addFrozenStateChangeCallback(this);
+                } catch (UnsupportedOperationException e) {
+                    // Ignore the exception.  The callback is not supported on this platform or on
+                    // this binder.  The callback is never supported for local binders.  There is
+                    // no error: the UID importance listener will still operate.  A log message is
+                    // provided for debug.
+                    Slog.v(TAG, "FrozenStateChangeCallback not supported for pid " + mPid);
+                } catch (RemoteException e) {
+                    // This is unexpected.  Just give up.
+                    throw new RuntimeException(e);
                 }
             }
 
@@ -4182,7 +4177,7 @@
          */
         @GuardedBy("mCallback")
         private boolean hasPendingAndIsReadyLocked() {
-            return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty();
+            return isReadyLocked() && mPendingEvents != null && !mPendingEvents.isEmpty() && mAlive;
         }
 
         /**
@@ -4190,7 +4185,7 @@
          * receive events and there are pending events to be delivered.
          * This is only used if {@link deferDisplayEventsWhenFrozen()} is true.
          */
-        public boolean setFrozen(boolean frozen) {
+        private boolean setFrozen(boolean frozen) {
             synchronized (mCallback) {
                 mFrozen = frozen;
                 return hasPendingAndIsReadyLocked();
@@ -4211,6 +4206,9 @@
 
         @Override
         public void binderDied() {
+            synchronized (mCallback) {
+                mAlive = false;
+            }
             if (DEBUG || extraLogging(mPackageName)) {
                 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
             }
@@ -4221,6 +4219,14 @@
             onCallbackDied(this);
         }
 
+        @Override
+        public void onFrozenStateChanged(@NonNull IBinder who, int state) {
+            if (setFrozen(state == FrozenStateChangeCallback.STATE_FROZEN)) {
+                Message msg = mHandler.obtainMessage(MSG_DISPATCH_PENDING_PROCESS_EVENTS, this);
+                mHandler.sendMessage(msg);
+            }
+        }
+
         /**
          * @return {@code false} if RemoteException happens; otherwise {@code true} for
          * success.  This returns true even if the event was deferred because the remote client is
@@ -4286,8 +4292,9 @@
             switch (event) {
                 case DisplayManagerGlobal.EVENT_DISPLAY_ADDED:
                     return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED) != 0;
-                case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
-                    return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED) != 0;
+                case DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED:
+                    return (mask & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED)
+                            != 0;
                 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
                     return (mask
                             & DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BRIGHTNESS_CHANGED)
@@ -4386,7 +4393,7 @@
         // This is only used if {@link deferDisplayEventsWhenFrozen()} is true.
         public boolean dispatchPending() {
             synchronized (mCallback) {
-                if (mPendingEvents == null || mPendingEvents.isEmpty()) {
+                if (mPendingEvents == null || mPendingEvents.isEmpty() || !mAlive) {
                     return true;
                 }
                 if (!isReadyLocked()) {
@@ -4542,7 +4549,8 @@
         public void registerCallback(IDisplayManagerCallback callback) {
             registerCallbackWithEventMask(callback,
                     DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-                    | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+                    | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+                    | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
                     | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED);
         }
 
@@ -4602,13 +4610,13 @@
             }
         }
 
+        @EnforcePermission(CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void connectWifiDisplay(String address) {
+            connectWifiDisplay_enforcePermission();
             if (address == null) {
                 throw new IllegalArgumentException("address must not be null");
             }
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to connect to a wifi display");
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -4633,13 +4641,13 @@
             }
         }
 
+        @EnforcePermission(CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void renameWifiDisplay(String address, String alias) {
+            renameWifiDisplay_enforcePermission();
             if (address == null) {
                 throw new IllegalArgumentException("address must not be null");
             }
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to rename to a wifi display");
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -4649,13 +4657,13 @@
             }
         }
 
+        @EnforcePermission(CONFIGURE_WIFI_DISPLAY)
         @Override // Binder call
         public void forgetWifiDisplay(String address) {
+            forgetWifiDisplay_enforcePermission();
             if (address == null) {
                 throw new IllegalArgumentException("address must not be null");
             }
-            mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
-                    "Permission required to forget to a wifi display");
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -4999,7 +5007,7 @@
             }
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override
         public BrightnessInfo getBrightnessInfo(int displayId) {
             getBrightnessInfo_enforcePermission();
@@ -5030,7 +5038,7 @@
             }
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryBrightness(int displayId, float brightness) {
             setTemporaryBrightness_enforcePermission();
@@ -5045,7 +5053,7 @@
             }
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setBrightness(int displayId, float brightness) {
             setBrightness_enforcePermission();
@@ -5069,12 +5077,11 @@
             }
         }
 
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public float getBrightness(int displayId) {
+            getBrightness_enforcePermission();
             float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
-                    "Permission required to set the display's brightness");
             final long token = Binder.clearCallingIdentity();
             try {
                 synchronized (mSyncRoot) {
@@ -5089,7 +5096,7 @@
             return brightness;
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
             setTemporaryAutoBrightnessAdjustment_enforcePermission();
@@ -5164,14 +5171,13 @@
             }
         }
 
+        @EnforcePermission(MODIFY_HDR_CONVERSION_MODE)
         @Override // Binder call
         public void setHdrConversionMode(HdrConversionMode hdrConversionMode) {
+            setHdrConversionMode_enforcePermission();
             if (!mIsHdrOutputControlEnabled) {
                 return;
             }
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.MODIFY_HDR_CONVERSION_MODE,
-                    "Permission required to set the HDR conversion mode.");
             final long token = Binder.clearCallingIdentity();
             try {
                 setHdrConversionModeInternal(hdrConversionMode);
@@ -5335,7 +5341,7 @@
                     ? ddc.getHdrBrightnessData().highestHdrSdrRatio : 1;
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public float[] getDozeBrightnessSensorValueToBrightness(int displayId) {
             getDozeBrightnessSensorValueToBrightness_enforcePermission();
@@ -5348,7 +5354,7 @@
             return ddc.getDozeBrightnessSensorValueToBrightness();
         }
 
-        @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS)
+        @EnforcePermission(CONTROL_DISPLAY_BRIGHTNESS)
         @Override // Binder call
         public float getDefaultDozeBrightness(int displayId) {
             getDefaultDozeBrightness_enforcePermission();
@@ -5839,6 +5845,15 @@
         }
 
         @Override
+        public int getGroupIdForDisplay(int displayId) {
+            synchronized (mSyncRoot) {
+                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
+                if (display == null) return Display.INVALID_DISPLAY_GROUP;
+                return display.getDisplayInfoLocked().displayGroupId;
+            }
+        }
+
+        @Override
         public DisplayManagerInternal.DisplayOffloadSession registerDisplayOffloader(
                 int displayId, @NonNull DisplayManagerInternal.DisplayOffloader displayOffloader) {
             if (!mFlags.isDisplayOffloadEnabled()) {
@@ -6057,6 +6072,7 @@
      * Return the value of the pause
      */
     private static boolean deferDisplayEventsWhenFrozen() {
-        return com.android.server.am.Flags.deferDisplayEventsWhenFrozen();
+        return android.os.Flags.binderFrozenStateChangeCallback()
+                && com.android.server.am.Flags.deferDisplayEventsWhenFrozen();
     }
 }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2f82b2a..92f5cab 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1638,7 +1638,7 @@
         // brightness sources (such as an app override) are not saved to the setting, but should be
         // reflected in HBM calculations.
         mBrightnessRangeController.onBrightnessChanged(brightnessState, unthrottledBrightnessState,
-                clampedState.getBrightnessMaxReason());
+                clampedState);
 
         // Animate the screen brightness when the screen is on or dozing.
         // Skip the animation when the screen is off or suspended.
diff --git a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
index 5b78726..461a9f3 100644
--- a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
+++ b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java
@@ -85,13 +85,26 @@
     }
 
     /**
+     * Update the topology with display changes.
+     * @param info The new display info
+     */
+    void onDisplayChanged(DisplayInfo info) {
+        synchronized (mSyncRoot) {
+            if (mTopology.updateDisplay(info.displayId, getWidth(info), getHeight(info))) {
+                sendTopologyUpdateLocked();
+            }
+        }
+    }
+
+    /**
      * Remove a display from the topology.
      * @param displayId The logical display ID
      */
     void onDisplayRemoved(int displayId) {
         synchronized (mSyncRoot) {
-            mTopology.removeDisplay(displayId);
-            sendTopologyUpdateLocked();
+            if (mTopology.removeDisplay(displayId)) {
+                sendTopologyUpdateLocked();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 6be0c12..0334aa5 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -102,7 +102,8 @@
         BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
 
     private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
-    private boolean mIsHdrLayerPresent = false;
+    @VisibleForTesting
+    boolean mIsHdrLayerPresent = false;
     // mMaxDesiredHdrSdrRatio should only be applied when there is a valid backlight->nits mapping
     private float mMaxDesiredHdrSdrRatio = DEFAULT_MAX_DESIRED_HDR_SDR_RATIO;
     private boolean mForceHbmChangeCallback = false;
@@ -387,6 +388,18 @@
         mHdrBoostDisabled = true;
         unregisterHdrListener();
     }
+    /**
+     * Hdr boost can be applied by
+     * {@link com.android.server.display.brightness.clamper.HdrBrightnessModifier}, in this case
+     * HBMController should not consume HBM time budget
+     */
+    void onHdrBoostApplied(boolean applied) {
+        // We need to update mIsHdrLayerPresent flag only if HDR boost is controlled  by other
+        // component and disabled here
+        if (mHdrBoostDisabled) {
+            mIsHdrLayerPresent = applied;
+        }
+    }
 
     private long calculateRemainingTime(long currentTime) {
         if (!deviceSupportsHbm()) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 79592a65..0069215 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -81,7 +81,7 @@
 
     public static final int LOGICAL_DISPLAY_EVENT_BASE = 0;
     public static final int LOGICAL_DISPLAY_EVENT_ADDED = 1 << 0;
-    public static final int LOGICAL_DISPLAY_EVENT_CHANGED = 1 << 1;
+    public static final int LOGICAL_DISPLAY_EVENT_BASIC_CHANGED = 1 << 1;
     public static final int LOGICAL_DISPLAY_EVENT_REMOVED = 1 << 2;
     public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 1 << 3;
     public static final int LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED = 1 << 4;
@@ -172,9 +172,7 @@
 
     /**
      * Has an entry for every logical display that the rest of the system has been notified about.
-     * Any entry in here requires us to send a {@link  LOGICAL_DISPLAY_EVENT_REMOVED} event when it
-     * is deleted or {@link  LOGICAL_DISPLAY_EVENT_CHANGED} when it is changed. The values are any
-     * of the {@code UPDATE_STATE_*} constant types.
+     * The values are any of the {@code UPDATE_STATE_*} constant types.
      */
     private final SparseIntArray mUpdatedLogicalDisplays = new SparseIntArray();
 
@@ -811,7 +809,8 @@
             final boolean isCurrentlyEnabled = display.isEnabledLocked();
             int logicalDisplayEventMask = mLogicalDisplaysToUpdate
                     .get(displayId, LOGICAL_DISPLAY_EVENT_BASE);
-
+            boolean hasBasicInfoChanged =
+                    !mTempDisplayInfo.equals(newDisplayInfo, /* compareRefreshRate */ false);
             // The display is no longer valid and needs to be removed.
             if (!display.isValidLocked()) {
                 // Remove from group
@@ -863,19 +862,28 @@
                 int event = isCurrentlyEnabled ? LOGICAL_DISPLAY_EVENT_ADDED :
                         LOGICAL_DISPLAY_EVENT_REMOVED;
                 logicalDisplayEventMask |= event;
-            } else if (wasDirty || !mTempDisplayInfo.equals(newDisplayInfo)) {
+            } else if (wasDirty) {
                 // If only the hdr/sdr ratio changed, then send just the event for that case
                 if ((diff == DisplayDeviceInfo.DIFF_HDR_SDR_RATIO)) {
                     logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED;
                 } else {
-                    logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_CHANGED;
+                    logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_BASIC_CHANGED
+                            | LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED
+                            | LOGICAL_DISPLAY_EVENT_STATE_CHANGED;
                 }
+            } else if (hasBasicInfoChanged
+                    || mTempDisplayInfo.getRefreshRate() != newDisplayInfo.getRefreshRate()) {
+                // If only the hdr/sdr ratio changed, then send just the event for that case
+                if ((diff == DisplayDeviceInfo.DIFF_HDR_SDR_RATIO)) {
+                    logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED;
+                } else {
 
-                if (mFlags.isDisplayListenerPerformanceImprovementsEnabled()) {
+                    if (hasBasicInfoChanged) {
+                        logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_BASIC_CHANGED;
+                    }
                     logicalDisplayEventMask
                             |= updateAndGetMaskForDisplayPropertyChanges(newDisplayInfo);
                 }
-
                 // The display is involved in a display layout transition
             } else if (updateState == UPDATE_STATE_TRANSITION) {
                 logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION;
@@ -891,7 +899,8 @@
                 // things like display cutouts.
                 display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo);
                 if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) {
-                    logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_CHANGED;
+                    logicalDisplayEventMask |= LOGICAL_DISPLAY_EVENT_BASIC_CHANGED
+                            | LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED;
                 }
             }
             mLogicalDisplaysToUpdate.put(displayId, logicalDisplayEventMask);
@@ -930,7 +939,7 @@
         if (mFlags.isConnectedDisplayManagementEnabled()) {
             sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DISCONNECTED);
         }
-        sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED);
+        sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_BASIC_CHANGED);
         sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED);
         sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_STATE_CHANGED);
         sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
@@ -962,7 +971,8 @@
             mask |= LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED;
         }
 
-        if (mTempDisplayInfo.state != newDisplayInfo.state) {
+        if (mFlags.isDisplayListenerPerformanceImprovementsEnabled()
+                && mTempDisplayInfo.state != newDisplayInfo.state) {
             mask |= LOGICAL_DISPLAY_EVENT_STATE_CHANGED;
         }
         return mask;
@@ -1357,8 +1367,6 @@
                 return "added";
             case LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION:
                 return "transition";
-            case LOGICAL_DISPLAY_EVENT_CHANGED:
-                return "changed";
             case LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
                 return "framerate_override";
             case LOGICAL_DISPLAY_EVENT_SWAPPED:
@@ -1375,6 +1383,8 @@
                 return "state_changed";
             case LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED:
                 return "refresh_rate_changed";
+            case LOGICAL_DISPLAY_EVENT_BASIC_CHANGED:
+                return "basic_changed";
         }
         return null;
     }
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index 85b6bbb..addfbf1 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -46,10 +46,6 @@
             Flags.FLAG_ENABLE_CONNECTED_DISPLAY_MANAGEMENT,
             Flags::enableConnectedDisplayManagement);
 
-    private final FlagState mHdrClamperFlagState = new FlagState(
-            Flags.FLAG_ENABLE_HDR_CLAMPER,
-            Flags::enableHdrClamper);
-
     private final FlagState mAdaptiveToneImprovements1 = new FlagState(
             Flags.FLAG_ENABLE_ADAPTIVE_TONE_IMPROVEMENTS_1,
             Flags::enableAdaptiveToneImprovements1);
@@ -278,11 +274,6 @@
         return mConnectedDisplayManagementFlagState.isEnabled();
     }
 
-    /** Returns whether hdr clamper is enabled on not. */
-    public boolean isHdrClamperEnabled() {
-        return mHdrClamperFlagState.isEnabled();
-    }
-
     /** Returns whether power throttling clamper is enabled on not. */
     public boolean isPowerThrottlingClamperEnabled() {
         return mPowerThrottlingClamperFlagState.isEnabled();
@@ -585,7 +576,6 @@
         pw.println(" " + mDisplayOffloadFlagState);
         pw.println(" " + mExternalDisplayLimitModeState);
         pw.println(" " + mDisplayTopology);
-        pw.println(" " + mHdrClamperFlagState);
         pw.println(" " + mPowerThrottlingClamperFlagState);
         pw.println(" " + mEvenDimmerFlagState);
         pw.println(" " + mSmallAreaDetectionFlagState);
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 3358f72..eccbbb1 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -37,14 +37,6 @@
 }
 
 flag {
-    name: "enable_hdr_clamper"
-    namespace: "display_manager"
-    description: "Feature flag for HDR Clamper"
-    bug: "295100043"
-    is_fixed_read_only: true
-}
-
-flag {
     name: "enable_power_throttling_clamper"
     namespace: "display_manager"
     description: "Feature flag for Power Throttling Clamper"
@@ -96,7 +88,7 @@
     name: "display_topology"
     namespace: "display_manager"
     description: "Display topology for moving cursors and windows between extended displays"
-    bug: "278199220"
+    bug: "364906028"
     is_fixed_read_only: true
 }
 
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 02e2882..1dd4a9b 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -2080,10 +2080,13 @@
 
             restartObserver();
             mDeviceConfigDisplaySettings.startListening();
+            registerDisplayListener();
+        }
 
+        private void registerDisplayListener() {
             mInjector.registerDisplayListener(this, mHandler,
-                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED,
-                    DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
+                    DisplayManager.EVENT_TYPE_DISPLAY_CHANGED,
+                    DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS);
         }
 
         private void setLoggingEnabled(boolean loggingEnabled) {
@@ -2883,8 +2886,8 @@
             }
             mDisplayManagerInternal = mInjector.getDisplayManagerInternal();
             mInjector.registerDisplayListener(this, mHandler,
-                    DisplayManager.EVENT_FLAG_DISPLAY_REMOVED,
-                    DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS);
+                    DisplayManager.EVENT_TYPE_DISPLAY_REMOVED,
+                    DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS);
         }
 
         /**
diff --git a/services/core/java/com/android/server/display/mode/ProximitySensorObserver.java b/services/core/java/com/android/server/display/mode/ProximitySensorObserver.java
index 11418c1..0f78f0d 100644
--- a/services/core/java/com/android/server/display/mode/ProximitySensorObserver.java
+++ b/services/core/java/com/android/server/display/mode/ProximitySensorObserver.java
@@ -70,10 +70,14 @@
                 mDozeStateByDisplay.put(d.getDisplayId(), mInjector.isDozeState(d));
             }
         }
+        registerDisplayListener();
+    }
+
+    private void registerDisplayListener() {
         mInjector.registerDisplayListener(this, BackgroundThread.getHandler(),
-                DisplayManager.EVENT_FLAG_DISPLAY_ADDED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
+                DisplayManager.EVENT_TYPE_DISPLAY_ADDED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_CHANGED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_REMOVED);
     }
 
     @GuardedBy("mSensorObserverLock")
diff --git a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
index 625b6bb..4ec9e83 100644
--- a/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
+++ b/services/core/java/com/android/server/display/mode/SkinThermalStatusObserver.java
@@ -83,14 +83,17 @@
         if (!mInjector.registerThermalServiceListener(this)) {
             return;
         }
-
-        mInjector.registerDisplayListener(this, mHandler,
-                DisplayManager.EVENT_FLAG_DISPLAY_ADDED | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
-
+        registerDisplayListener();
         populateInitialDisplayInfo();
     }
 
+    private void registerDisplayListener() {
+        mInjector.registerDisplayListener(this, mHandler,
+                DisplayManager.EVENT_TYPE_DISPLAY_ADDED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_CHANGED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_REMOVED);
+    }
+
     void setLoggingEnabled(boolean enabled) {
         mLoggingEnabled = enabled;
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index a8d5696..c384b54 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -1345,7 +1345,10 @@
             iter.remove();
         }
         if (mPendingActionClearedCallback != null) {
-            mPendingActionClearedCallback.onCleared(this);
+            PendingActionClearedCallback callback = mPendingActionClearedCallback;
+            // To prevent from calling the callback again during handling the callback itself.
+            mPendingActionClearedCallback = null;
+            callback.onCleared(this);
         }
     }
 
diff --git a/services/core/java/com/android/server/input/InputGestureManager.java b/services/core/java/com/android/server/input/InputGestureManager.java
index 8681ea5..9f785ac 100644
--- a/services/core/java/com/android/server/input/InputGestureManager.java
+++ b/services/core/java/com/android/server/input/InputGestureManager.java
@@ -173,7 +173,7 @@
                 ),
                 createKeyGesture(
                         KeyEvent.KEYCODE_DPAD_LEFT,
-                        KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                        KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                         KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT
                 ),
                 createKeyGesture(
@@ -183,7 +183,7 @@
                 ),
                 createKeyGesture(
                         KeyEvent.KEYCODE_DPAD_RIGHT,
-                        KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                        KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
                         KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT
                 ),
                 createKeyGesture(
@@ -217,22 +217,22 @@
                     KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_MINUS,
                     KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT));
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_EQUALS,
                     KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN));
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_LEFT,
-                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT));
+                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_RIGHT,
-                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT));
+                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_UP,
-                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP));
+                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_DPAD_DOWN,
-                    KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON,
-                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN));
+                    KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
+                    KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN));
             systemShortcuts.add(createKeyGesture(KeyEvent.KEYCODE_M,
                     KeyEvent.META_META_ON | KeyEvent.META_ALT_ON,
                     KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_MAGNIFICATION));
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index bf08563..56cb6f49 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -69,6 +69,8 @@
                 Map.entry(Settings.System.getUriFor(
                                 Settings.System.MOUSE_SWAP_PRIMARY_BUTTON),
                         (reason) -> updateMouseSwapPrimaryButton()),
+                Map.entry(Settings.System.getUriFor(Settings.System.MOUSE_SCROLLING_ACCELERATION),
+                        (reason) -> updateMouseScrollingAcceleration()),
                 Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_POINTER_SPEED),
                         (reason) -> updateTouchpadPointerSpeed()),
                 Map.entry(Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING),
@@ -184,6 +186,11 @@
                 InputSettings.isMouseSwapPrimaryButtonEnabled(mContext));
     }
 
+    private void updateMouseScrollingAcceleration() {
+        mNative.setMouseScrollingAccelerationEnabled(
+                InputSettings.isMouseScrollingAccelerationEnabled(mContext));
+    }
+
     private void updateTouchpadPointerSpeed() {
         mNative.setTouchpadPointerSpeed(
                 constrainPointerSpeedValue(InputSettings.getTouchpadPointerSpeed(mContext)));
diff --git a/services/core/java/com/android/server/input/NativeInputManagerService.java b/services/core/java/com/android/server/input/NativeInputManagerService.java
index c72f7c0..ab5a680 100644
--- a/services/core/java/com/android/server/input/NativeInputManagerService.java
+++ b/services/core/java/com/android/server/input/NativeInputManagerService.java
@@ -134,6 +134,8 @@
 
     void setMouseReverseVerticalScrollingEnabled(boolean enabled);
 
+    void setMouseScrollingAccelerationEnabled(boolean enabled);
+
     void setMouseSwapPrimaryButtonEnabled(boolean enabled);
 
     void setTouchpadPointerSpeed(int speed);
@@ -421,6 +423,9 @@
         public native void setMouseReverseVerticalScrollingEnabled(boolean enabled);
 
         @Override
+        public native void setMouseScrollingAccelerationEnabled(boolean enabled);
+
+        @Override
         public native void setMouseSwapPrimaryButtonEnabled(boolean enabled);
 
         @Override
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index 477660d..4f3aa06 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -492,8 +492,8 @@
         }
 
         if (getCurToken() != null) {
-            removeCurrentToken();
             mService.resetSystemUiLocked(this);
+            removeCurrentToken();
             mAutofillController.onResetSystemUi();
         }
 
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
index 957307a..7b59d6f1 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java
@@ -482,10 +482,7 @@
     /* package */
     static Message createHalMessage(HubMessage message) {
         Message outMessage = new Message();
-        outMessage.flags =
-                message.getDeliveryParams().isResponseRequired()
-                        ? Message.FLAG_REQUIRES_DELIVERY_STATUS
-                        : 0;
+        outMessage.flags = message.isResponseRequired() ? Message.FLAG_REQUIRES_DELIVERY_STATUS : 0;
         outMessage.permissions = new String[0];
         outMessage.sequenceNumber = message.getMessageSequenceNumber();
         outMessage.type = message.getMessageType();
@@ -502,10 +499,9 @@
     /* package */
     static HubMessage createHubMessage(Message message) {
         boolean isReliable = (message.flags & Message.FLAG_REQUIRES_DELIVERY_STATUS) != 0;
-        return HubMessage.createMessage(
-                message.type,
-                message.content,
-                HubMessage.DeliveryParams.makeBasic().setResponseRequired(isReliable));
+        return new HubMessage.Builder(message.type, message.content)
+                .setResponseRequired(isReliable)
+                .build();
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyGnssAssistanceProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyGnssAssistanceProvider.java
new file mode 100644
index 0000000..6cab60c
--- /dev/null
+++ b/services/core/java/com/android/server/location/provider/proxy/ProxyGnssAssistanceProvider.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location.provider.proxy;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.location.provider.GnssAssistanceProviderBase;
+import android.location.provider.IGnssAssistanceCallback;
+import android.location.provider.IGnssAssistanceProvider;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.server.servicewatcher.CurrentUserServiceSupplier;
+import com.android.server.servicewatcher.ServiceWatcher;
+
+/**
+ * Proxy for IGnssAssitanceProvider implementations.
+ */
+public class ProxyGnssAssistanceProvider {
+
+    private static final String TAG = "GnssAssistanceProxy";
+    /**
+     * Creates and registers this proxy. If no suitable service is available for the proxy, returns
+     * null.
+     */
+    @Nullable
+    public static ProxyGnssAssistanceProvider createAndRegister(Context context) {
+        ProxyGnssAssistanceProvider proxy = new ProxyGnssAssistanceProvider(context);
+        if (proxy.register()) {
+            return proxy;
+        } else {
+            return null;
+        }
+    }
+
+    private final ServiceWatcher mServiceWatcher;
+
+    private ProxyGnssAssistanceProvider(Context context) {
+        mServiceWatcher =
+                ServiceWatcher.create(
+                        context,
+                        TAG,
+                        CurrentUserServiceSupplier.createFromConfig(
+                                context,
+                                GnssAssistanceProviderBase.ACTION_GNSS_ASSISTANCE_PROVIDER,
+                                com.android.internal.R.bool.config_enableGnssAssistanceOverlay,
+                                com.android.internal.R.string
+                                        .config_gnssAssistanceProviderPackageName),
+                        /* serviceListener= */ null);
+    }
+
+    private boolean register() {
+        boolean resolves = mServiceWatcher.checkServiceResolves();
+        if (resolves) {
+            mServiceWatcher.register();
+        }
+        return resolves;
+    }
+
+    /**
+     * Request GNSS assistance.
+     */
+    public void request(IGnssAssistanceCallback callback) {
+        mServiceWatcher.runOnBinder(
+                new ServiceWatcher.BinderOperation() {
+                    @Override
+                    public void run(IBinder binder) throws RemoteException {
+                        IGnssAssistanceProvider.Stub.asInterface(binder).request(callback);
+                    }
+
+                    @Override
+                    public void onError(Throwable t) {
+                        try {
+                            Log.w(TAG, "Error on requesting GnssAssistance: " + t);
+                            callback.onError();
+                        } catch (RemoteException e) {
+                            // ignore
+                        }
+                    }
+                });
+    }
+}
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 58c8450..0d6e502 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
+import android.media.MediaRoute2ProviderService.Reason;
 import android.media.MediaRouter2;
 import android.media.MediaRouter2Utils;
 import android.media.RouteDiscoveryPreference;
@@ -123,6 +124,13 @@
         }
     }
 
+    /** Calls {@link Callback#onRequestFailed} with the given id and reason. */
+    protected void notifyRequestFailed(long requestId, @Reason int reason) {
+        if (mCallback != null) {
+            mCallback.onRequestFailed(/* provider= */ this, requestId, reason);
+        }
+    }
+
     void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo) {
         setProviderState(providerInfo);
         notifyProviderState();
@@ -171,11 +179,34 @@
         void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
         void onSessionCreated(@NonNull MediaRoute2Provider provider,
                 long requestId, @Nullable RoutingSessionInfo sessionInfo);
-        void onSessionUpdated(@NonNull MediaRoute2Provider provider,
-                @NonNull RoutingSessionInfo sessionInfo);
+
+        /**
+         * Called when there's a session info change.
+         *
+         * <p>If the provided {@code sessionInfo} has a null {@link
+         * RoutingSessionInfo#getClientPackageName()}, that means that it's applicable to all
+         * packages. We call this type of routing session "global". This is typically used for
+         * system provided {@link RoutingSessionInfo}. However, some applications may be exempted
+         * from the global routing sessions, because their media is being routed using a session
+         * different from the global routing session.
+         *
+         * @param provider The provider that owns the session that changed.
+         * @param sessionInfo The new {@link RoutingSessionInfo}.
+         * @param packageNamesWithRoutingSessionOverrides The names of packages that are not
+         *     affected by global session changes. This set may only be non-empty when the {@code
+         *     sessionInfo} is for the global session, and therefore has no {@link
+         *     RoutingSessionInfo#getClientPackageName()}.
+         */
+        void onSessionUpdated(
+                @NonNull MediaRoute2Provider provider,
+                @NonNull RoutingSessionInfo sessionInfo,
+                Set<String> packageNamesWithRoutingSessionOverrides);
+
         void onSessionReleased(@NonNull MediaRoute2Provider provider,
                 @NonNull RoutingSessionInfo sessionInfo);
-        void onRequestFailed(@NonNull MediaRoute2Provider provider, long requestId, int reason);
+
+        void onRequestFailed(
+                @NonNull MediaRoute2Provider provider, long requestId, @Reason int reason);
     }
 
     /**
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index f09be2c..d6f7d3b 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import static android.media.MediaRoute2ProviderService.REASON_REJECTED;
 import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
 
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
@@ -31,6 +32,7 @@
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
+import android.media.MediaRoute2ProviderService.Reason;
 import android.media.RouteDiscoveryPreference;
 import android.media.RoutingSessionInfo;
 import android.os.Bundle;
@@ -41,6 +43,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Slog;
@@ -89,6 +92,12 @@
             mRequestIdToSessionCreationRequest;
 
     @GuardedBy("mLock")
+    private final Map<String, SystemMediaSessionCallback> mSystemSessionCallbacks;
+
+    @GuardedBy("mLock")
+    private final LongSparseArray<SystemMediaSessionCallback> mRequestIdToSystemSessionRequest;
+
+    @GuardedBy("mLock")
     private final Map<String, SessionCreationOrTransferRequest> mSessionOriginalIdToTransferRequest;
 
     MediaRoute2ProviderServiceProxy(
@@ -102,6 +111,8 @@
         mContext = Objects.requireNonNull(context, "Context must not be null.");
         mRequestIdToSessionCreationRequest = new LongSparseArray<>();
         mSessionOriginalIdToTransferRequest = new HashMap<>();
+        mRequestIdToSystemSessionRequest = new LongSparseArray<>();
+        mSystemSessionCallbacks = new ArrayMap<>();
         mIsSelfScanOnlyProvider = isSelfScanOnlyProvider;
         mSupportsSystemMediaRouting = supportsSystemMediaRouting;
         mUserId = userId;
@@ -236,6 +247,48 @@
         }
     }
 
+    /**
+     * Requests the creation of a system media routing session.
+     *
+     * @param requestId The id of the request.
+     * @param uid The uid of the package whose media to route, or {@link
+     *     android.os.Process#INVALID_UID} if not applicable (for example, if all the system's media
+     *     must be routed).
+     * @param packageName The package name to populate {@link
+     *     RoutingSessionInfo#getClientPackageName()}.
+     * @param routeId The id of the route to be initially {@link
+     *     RoutingSessionInfo#getSelectedRoutes()}.
+     * @param sessionHints An optional bundle with paramets.
+     * @param callback A {@link SystemMediaSessionCallback} to notify of session events.
+     * @see MediaRoute2ProviderService#onCreateSystemRoutingSession
+     */
+    public void requestCreateSystemMediaSession(
+            long requestId,
+            int uid,
+            String packageName,
+            String routeId,
+            @Nullable Bundle sessionHints,
+            @NonNull SystemMediaSessionCallback callback) {
+        if (!Flags.enableMirroringInMediaRouter2()) {
+            throw new IllegalStateException(
+                    "Unexpected call to requestCreateSystemMediaSession. Governing flag is"
+                            + " disabled.");
+        }
+        if (mConnectionReady) {
+            boolean binderRequestSucceeded =
+                    mActiveConnection.requestCreateSystemMediaSession(
+                            requestId, uid, packageName, routeId, sessionHints);
+            if (!binderRequestSucceeded) {
+                // notify failure.
+                return;
+            }
+            updateBinding();
+            synchronized (mLock) {
+                mRequestIdToSystemSessionRequest.put(requestId, callback);
+            }
+        }
+    }
+
     public boolean hasComponentName(String packageName, String className) {
         return mComponentName.getPackageName().equals(packageName)
                 && mComponentName.getClassName().equals(className);
@@ -292,7 +345,14 @@
                 mLastDiscoveryPreference != null
                         && mLastDiscoveryPreference.shouldPerformActiveScan()
                         && mSupportsSystemMediaRouting;
+        boolean bindDueToOngoingSystemMediaRoutingSessions = false;
+        if (Flags.enableMirroringInMediaRouter2()) {
+            synchronized (mLock) {
+                bindDueToOngoingSystemMediaRoutingSessions = !mSystemSessionCallbacks.isEmpty();
+            }
+        }
         if (!getSessionInfos().isEmpty()
+                || bindDueToOngoingSystemMediaRoutingSessions
                 || bindDueToManagerScan
                 || bindDueToSystemMediaRoutingSupport) {
             return true;
@@ -438,6 +498,14 @@
         String newSessionId = newSession.getId();
 
         synchronized (mLock) {
+            var systemMediaSessionCallback = mRequestIdToSystemSessionRequest.get(requestId);
+            if (systemMediaSessionCallback != null) {
+                mRequestIdToSystemSessionRequest.remove(requestId);
+                mSystemSessionCallbacks.put(newSession.getOriginalId(), systemMediaSessionCallback);
+                systemMediaSessionCallback.onSessionUpdate(newSession);
+                return;
+            }
+
             if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) {
                 newSession =
                         createSessionWithPopulatedTransferInitiationDataLocked(
@@ -569,6 +637,12 @@
 
         boolean found = false;
         synchronized (mLock) {
+            var sessionCallback = mSystemSessionCallbacks.get(releasedSession.getOriginalId());
+            if (sessionCallback != null) {
+                sessionCallback.onSessionReleased();
+                return;
+            }
+
             mSessionOriginalIdToTransferRequest.remove(releasedSession.getId());
             for (RoutingSessionInfo session : mSessionInfos) {
                 if (TextUtils.equals(session.getId(), releasedSession.getId())) {
@@ -602,7 +676,11 @@
 
     private void dispatchSessionUpdated(RoutingSessionInfo session) {
         mHandler.sendMessage(
-                obtainMessage(mCallback::onSessionUpdated, this, session));
+                obtainMessage(
+                        mCallback::onSessionUpdated,
+                        this,
+                        session,
+                        /* packageNamesWithRoutingSessionOverrides= */ Set.of()));
     }
 
     private void dispatchSessionReleased(RoutingSessionInfo session) {
@@ -645,6 +723,19 @@
                 for (RoutingSessionInfo sessionInfo : mSessionInfos) {
                     mCallback.onSessionReleased(this, sessionInfo);
                 }
+                if (Flags.enableMirroringInMediaRouter2()) {
+                    for (var callback : mSystemSessionCallbacks.values()) {
+                        callback.onSessionReleased();
+                    }
+                    mSystemSessionCallbacks.clear();
+                    int requestsSize = mRequestIdToSystemSessionRequest.size();
+                    for (int i = 0; i < requestsSize; i++) {
+                        var callback = mRequestIdToSystemSessionRequest.valueAt(i);
+                        var requestId = mRequestIdToSystemSessionRequest.keyAt(i);
+                        callback.onRequestFailed(requestId, REASON_REJECTED);
+                    }
+                    mSystemSessionCallbacks.clear();
+                }
                 mSessionInfos.clear();
                 mReleasingSessions.clear();
                 mRequestIdToSessionCreationRequest.clear();
@@ -673,6 +764,26 @@
                 pendingTransferCount);
     }
 
+    /**
+     * Callback for events related to system media sessions.
+     *
+     * @see MediaRoute2ProviderService#onCreateSystemRoutingSession
+     */
+    public interface SystemMediaSessionCallback {
+
+        /**
+         * Called when the corresponding session's {@link RoutingSessionInfo}, or upon the creation
+         * of the given session info.
+         */
+        void onSessionUpdate(@NonNull RoutingSessionInfo sessionInfo);
+
+        /** Called when the request with the given id fails for the given reason. */
+        void onRequestFailed(long requestId, @Reason int reason);
+
+        /** Called when the corresponding session is released. */
+        void onSessionReleased();
+    }
+
     // All methods in this class are called on the main thread.
     private final class ServiceConnectionImpl implements ServiceConnection {
 
@@ -739,6 +850,28 @@
             }
         }
 
+        /**
+         * Sends a system media session creation request to the provider service, and returns
+         * whether the request transaction succeeded.
+         *
+         * <p>The transaction might fail, for example, if the recipient process has died.
+         */
+        public boolean requestCreateSystemMediaSession(
+                long requestId,
+                int uid,
+                String packageName,
+                String routeId,
+                @Nullable Bundle sessionHints) {
+            try {
+                mService.requestCreateSystemMediaSession(
+                        requestId, uid, packageName, routeId, sessionHints);
+                return true;
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "requestCreateSystemMediaSession: Failed to deliver request.");
+            }
+            return false;
+        }
+
         public void releaseSession(long requestId, String sessionId) {
             try {
                 mService.releaseSession(requestId, sessionId);
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 58deffc..5e6737a4 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -846,33 +846,29 @@
         try {
             synchronized (mLock) {
                 UserRecord userRecord = getOrCreateUserRecordLocked(userId);
-                List<RoutingSessionInfo> sessionInfos;
+                SystemMediaRoute2Provider systemProvider = userRecord.mHandler.getSystemProvider();
                 if (hasSystemRoutingPermissions) {
-                    if (setDeviceRouteSelected && !Flags.enableMirroringInMediaRouter2()) {
+                    if (!Flags.enableMirroringInMediaRouter2() && setDeviceRouteSelected) {
                         // Return a fake system session that shows the device route as selected and
                         // available bluetooth routes as transferable.
-                        return userRecord.mHandler.getSystemProvider()
-                                .generateDeviceRouteSelectedSessionInfo(targetPackageName);
+                        return systemProvider.generateDeviceRouteSelectedSessionInfo(
+                                targetPackageName);
                     } else {
-                        sessionInfos = userRecord.mHandler.getSystemProvider().getSessionInfos();
-                        if (!sessionInfos.isEmpty()) {
-                            // Return a copy of the current system session with no modification,
-                            // except setting the client package name.
-                            return new RoutingSessionInfo.Builder(sessionInfos.get(0))
-                                    .setClientPackageName(targetPackageName)
-                                    .build();
+                        RoutingSessionInfo session =
+                                systemProvider.getSessionForPackage(targetPackageName);
+                        if (session != null) {
+                            return session;
                         } else {
                             Slog.w(TAG, "System provider does not have any session info.");
+                            return null;
                         }
                     }
                 } else {
-                    return new RoutingSessionInfo.Builder(
-                                    userRecord.mHandler.getSystemProvider().getDefaultSessionInfo())
+                    return new RoutingSessionInfo.Builder(systemProvider.getDefaultSessionInfo())
                             .setClientPackageName(targetPackageName)
                             .build();
                 }
             }
-            return null;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -2638,10 +2634,17 @@
         }
 
         @Override
-        public void onSessionUpdated(@NonNull MediaRoute2Provider provider,
-                @NonNull RoutingSessionInfo sessionInfo) {
-            sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionInfoChangedOnHandler,
-                    this, provider, sessionInfo));
+        public void onSessionUpdated(
+                @NonNull MediaRoute2Provider provider,
+                @NonNull RoutingSessionInfo sessionInfo,
+                Set<String> packageNamesWithRoutingSessionOverrides) {
+            sendMessage(
+                    PooledLambda.obtainMessage(
+                            UserHandler::onSessionInfoChangedOnHandler,
+                            this,
+                            provider,
+                            sessionInfo,
+                            packageNamesWithRoutingSessionOverrides));
         }
 
         @Override
@@ -3152,10 +3155,31 @@
                     toOriginalRequestId(uniqueRequestId), sessionInfo);
         }
 
-        private void onSessionInfoChangedOnHandler(@NonNull MediaRoute2Provider provider,
-                @NonNull RoutingSessionInfo sessionInfo) {
+        /**
+         * Implementation of {@link MediaRoute2Provider.Callback#onSessionUpdated}.
+         *
+         * <p>Must run on the thread that corresponds to this {@link UserHandler}.
+         */
+        private void onSessionInfoChangedOnHandler(
+                @NonNull MediaRoute2Provider provider,
+                @NonNull RoutingSessionInfo sessionInfo,
+                Set<String> packageNamesWithRoutingSessionOverrides) {
             List<ManagerRecord> managers = getManagerRecords();
             for (ManagerRecord manager : managers) {
+                if (Flags.enableMirroringInMediaRouter2()) {
+                    String targetPackageName = manager.mTargetPackageName;
+                    boolean skipDueToOverride =
+                            targetPackageName != null
+                                    && packageNamesWithRoutingSessionOverrides.contains(
+                                            targetPackageName);
+                    boolean sessionIsForTargetPackage =
+                            TextUtils.isEmpty(sessionInfo.getClientPackageName()) // is global.
+                                    || TextUtils.equals(
+                                            targetPackageName, sessionInfo.getClientPackageName());
+                    if (skipDueToOverride || !sessionIsForTargetPackage) {
+                        continue;
+                    }
+                }
                 manager.notifySessionUpdated(sessionInfo);
             }
 
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index b93846b..60fced1 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -62,7 +62,7 @@
     static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
 
     private final AudioManager mAudioManager;
-    private final Handler mHandler;
+    protected final Handler mHandler;
     private final Context mContext;
     private final UserHandle mUser;
 
@@ -116,7 +116,7 @@
                         () -> {
                             publishProviderState();
                             if (updateSessionInfosIfNeeded()) {
-                                notifySessionInfoUpdated();
+                                notifyGlobalSessionInfoUpdated();
                             }
                         });
 
@@ -129,7 +129,7 @@
                                         () -> {
                                             publishProviderState();
                                             if (updateSessionInfosIfNeeded()) {
-                                                notifySessionInfoUpdated();
+                                                notifyGlobalSessionInfoUpdated();
                                             }
                                         }));
     }
@@ -161,7 +161,7 @@
     public void setCallback(Callback callback) {
         super.setCallback(callback);
         notifyProviderState();
-        notifySessionInfoUpdated();
+        notifyGlobalSessionInfoUpdated();
     }
 
     @Override
@@ -296,7 +296,7 @@
 
         if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()
                 && updateSessionInfosIfNeeded()) {
-            notifySessionInfoUpdated();
+            notifyGlobalSessionInfoUpdated();
         }
     }
 
@@ -327,6 +327,23 @@
     }
 
     /**
+     * Returns the {@link RoutingSessionInfo} that corresponds to the package with the given name.
+     */
+    public RoutingSessionInfo getSessionForPackage(String targetPackageName) {
+        synchronized (mLock) {
+            if (!mSessionInfos.isEmpty()) {
+                // Return a copy of the current system session with no modification,
+                // except setting the client package name.
+                return new RoutingSessionInfo.Builder(mSessionInfos.get(0))
+                        .setClientPackageName(targetPackageName)
+                        .build();
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /**
      * Builds a system {@link RoutingSessionInfo} with the selected route set to the currently
      * selected <b>device</b> route (wired or built-in, but not bluetooth) and transferable routes
      * set to the currently available (connected) bluetooth routes.
@@ -626,20 +643,21 @@
         notifyProviderState();
     }
 
-    void notifySessionInfoUpdated() {
+    void notifyGlobalSessionInfoUpdated() {
         if (mCallback == null) {
             return;
         }
 
         RoutingSessionInfo sessionInfo;
         synchronized (mLock) {
-            sessionInfo = mSessionInfos.get(0);
-            if (sessionInfo == null) {
+            if (mSessionInfos.isEmpty()) {
                 return;
             }
+            sessionInfo = mSessionInfos.get(0);
         }
 
-        mCallback.onSessionUpdated(this, sessionInfo);
+        mCallback.onSessionUpdated(
+                this, sessionInfo, /* packageNamesWithRoutingSessionOverrides= */ Set.of());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
index 7dc30ab..8931e3a 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java
@@ -18,23 +18,33 @@
 
 import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
+import android.media.MediaRoute2ProviderService.Reason;
+import android.media.MediaRouter2Utils;
 import android.media.RoutingSessionInfo;
+import android.os.Binder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.UserHandle;
-import android.util.ArraySet;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.LongSparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.media.MediaRoute2ProviderServiceProxy.SystemMediaSessionCallback;
 
-import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Stream;
 
 /**
@@ -48,11 +58,33 @@
     private static final String ROUTE_ID_PREFIX_SYSTEM = "SYSTEM";
     private static final String ROUTE_ID_SYSTEM_SEPARATOR = ".";
 
+    private final PackageManager mPackageManager;
+
     @GuardedBy("mLock")
     private MediaRoute2ProviderInfo mLastSystemProviderInfo;
 
     @GuardedBy("mLock")
-    private final Map<String, ProviderProxyRecord> mProxyRecords = new HashMap<>();
+    private final Map<String, ProviderProxyRecord> mProxyRecords = new ArrayMap<>();
+
+    /**
+     * Maps package names to corresponding sessions maintained by {@link MediaRoute2ProviderService
+     * provider services}.
+     */
+    @GuardedBy("mLock")
+    private final Map<String, SystemMediaSessionRecord> mPackageNameToSessionRecord =
+            new ArrayMap<>();
+
+    /**
+     * Maps route {@link MediaRoute2Info#getOriginalId original ids} to the id of the {@link
+     * MediaRoute2ProviderService provider service} that manages the corresponding route.
+     */
+    @GuardedBy("mLock")
+    private final Map<String, String> mOriginalRouteIdToProviderId = new ArrayMap<>();
+
+    /** Maps request ids to pending session creation callbacks. */
+    @GuardedBy("mLock")
+    private final LongSparseArray<SystemMediaSessionCallbackImpl> mPendingSessionCreations =
+            new LongSparseArray<>();
 
     private static final ComponentName COMPONENT_NAME =
             new ComponentName(
@@ -69,6 +101,128 @@
 
     private SystemMediaRoute2Provider2(Context context, UserHandle user, Looper looper) {
         super(context, COMPONENT_NAME, user, looper);
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    public void transferToRoute(
+            long requestId,
+            @NonNull UserHandle clientUserHandle,
+            @NonNull String clientPackageName,
+            String sessionOriginalId,
+            String routeOriginalId,
+            int transferReason) {
+        synchronized (mLock) {
+            var targetProviderProxyId = mOriginalRouteIdToProviderId.get(routeOriginalId);
+            var targetProviderProxyRecord = mProxyRecords.get(targetProviderProxyId);
+            // Holds the target route, if it's managed by a provider service. Holds null otherwise.
+            var serviceTargetRoute =
+                    targetProviderProxyRecord != null
+                            ? targetProviderProxyRecord.getRouteByOriginalId(routeOriginalId)
+                            : null;
+            var existingSessionRecord = mPackageNameToSessionRecord.get(clientPackageName);
+            if (existingSessionRecord != null) {
+                var existingSession = existingSessionRecord.mSourceSessionInfo;
+                if (targetProviderProxyId != null
+                        && TextUtils.equals(
+                                targetProviderProxyId, existingSession.getProviderId())) {
+                    // The currently selected route and target route both belong to the same
+                    // provider. We tell the provider to handle the transfer.
+                    targetProviderProxyRecord.requestTransfer(
+                            existingSession.getOriginalId(), serviceTargetRoute);
+                } else {
+                    // The target route is handled by a provider other than the target one. We need
+                    // to release the existing session.
+                    var currentProxyRecord = existingSessionRecord.getProxyRecord();
+                    if (currentProxyRecord != null) {
+                        currentProxyRecord.releaseSession(
+                                requestId, existingSession.getOriginalId());
+                        existingSessionRecord.removeSelfFromSessionMap();
+                    }
+                }
+            }
+
+            if (serviceTargetRoute != null) {
+                boolean isGlobalSession = TextUtils.isEmpty(clientPackageName);
+                int uid;
+                if (isGlobalSession) {
+                    uid = Process.INVALID_UID;
+                } else {
+                    uid = fetchUid(clientPackageName, clientUserHandle);
+                    if (uid == Process.INVALID_UID) {
+                        throw new IllegalArgumentException(
+                                "Cannot resolve transfer for "
+                                        + clientPackageName
+                                        + " and "
+                                        + clientUserHandle);
+                    }
+                }
+                var pendingCreationCallback =
+                        new SystemMediaSessionCallbackImpl(
+                                targetProviderProxyId, requestId, clientPackageName);
+                mPendingSessionCreations.put(requestId, pendingCreationCallback);
+                targetProviderProxyRecord.requestCreateSystemMediaSession(
+                        requestId,
+                        uid,
+                        clientPackageName,
+                        routeOriginalId,
+                        pendingCreationCallback);
+            } else {
+                // The target route is not provided by any of the services. Assume it's a system
+                // provided route.
+                super.transferToRoute(
+                        requestId,
+                        clientUserHandle,
+                        clientPackageName,
+                        sessionOriginalId,
+                        routeOriginalId,
+                        transferReason);
+            }
+        }
+    }
+
+    @Nullable
+    @Override
+    public RoutingSessionInfo getSessionForPackage(String packageName) {
+        synchronized (mLock) {
+            var systemSession = super.getSessionForPackage(packageName);
+            if (systemSession == null) {
+                return null;
+            }
+            var overridingSession = mPackageNameToSessionRecord.get(packageName);
+            if (overridingSession != null) {
+                var builder =
+                        new RoutingSessionInfo.Builder(overridingSession.mTranslatedSessionInfo)
+                                .setProviderId(mUniqueId)
+                                .setSystemSession(true);
+                for (var systemRoute : mLastSystemProviderInfo.getRoutes()) {
+                    builder.addTransferableRoute(systemRoute.getOriginalId());
+                }
+                return builder.build();
+            } else {
+                return systemSession;
+            }
+        }
+    }
+
+    /**
+     * Returns the uid that corresponds to the given name and user handle, or {@link
+     * Process#INVALID_UID} if a uid couldn't be found.
+     */
+    @SuppressLint("MissingPermission")
+    // We clear the calling identity before calling the package manager, and we are running on the
+    // system_server.
+    private int fetchUid(String clientPackageName, UserHandle clientUserHandle) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return mPackageManager.getApplicationInfoAsUser(
+                            clientPackageName, /* flags= */ 0, clientUserHandle)
+                    .uid;
+        } catch (PackageManager.NameNotFoundException e) {
+            return Process.INVALID_UID;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -85,21 +239,21 @@
             } else {
                 mProxyRecords.put(serviceProxy.mUniqueId, proxyRecord);
             }
-            setProviderState(buildProviderInfo());
+            updateProviderInfo();
         }
         updateSessionInfo();
         notifyProviderState();
-        notifySessionInfoUpdated();
+        notifyGlobalSessionInfoUpdated();
     }
 
     @Override
     public void onSystemProviderRoutesChanged(MediaRoute2ProviderInfo providerInfo) {
         synchronized (mLock) {
             mLastSystemProviderInfo = providerInfo;
-            setProviderState(buildProviderInfo());
+            updateProviderInfo();
         }
         updateSessionInfo();
-        notifySessionInfoUpdated();
+        notifyGlobalSessionInfoUpdated();
     }
 
     /**
@@ -116,10 +270,13 @@
             var builder = new RoutingSessionInfo.Builder(systemSessionInfo);
             mProxyRecords.values().stream()
                     .flatMap(ProviderProxyRecord::getRoutesStream)
-                    .map(MediaRoute2Info::getId)
+                    .map(MediaRoute2Info::getOriginalId)
                     .forEach(builder::addTransferableRoute);
             mSessionInfos.clear();
             mSessionInfos.add(builder.build());
+            for (var sessionRecords : mPackageNameToSessionRecord.values()) {
+                mSessionInfos.add(sessionRecords.mTranslatedSessionInfo);
+            }
         }
     }
 
@@ -129,13 +286,84 @@
      * provider services}.
      */
     @GuardedBy("mLock")
-    private MediaRoute2ProviderInfo buildProviderInfo() {
+    private void updateProviderInfo() {
         MediaRoute2ProviderInfo.Builder builder =
                 new MediaRoute2ProviderInfo.Builder(mLastSystemProviderInfo);
-        mProxyRecords.values().stream()
-                .flatMap(ProviderProxyRecord::getRoutesStream)
-                .forEach(builder::addRoute);
-        return builder.build();
+        mOriginalRouteIdToProviderId.clear();
+        for (var proxyRecord : mProxyRecords.values()) {
+            String proxyId = proxyRecord.mProxy.mUniqueId;
+            proxyRecord
+                    .getRoutesStream()
+                    .forEach(
+                            route -> {
+                                builder.addRoute(route);
+                                mOriginalRouteIdToProviderId.put(route.getOriginalId(), proxyId);
+                            });
+        }
+        setProviderState(builder.build());
+    }
+
+    @Override
+    /* package */ void notifyGlobalSessionInfoUpdated() {
+        if (mCallback == null) {
+            return;
+        }
+
+        RoutingSessionInfo sessionInfo;
+        Set<String> packageNamesWithRoutingSessionOverrides;
+        synchronized (mLock) {
+            if (mSessionInfos.isEmpty()) {
+                return;
+            }
+            packageNamesWithRoutingSessionOverrides = mPackageNameToSessionRecord.keySet();
+            sessionInfo = mSessionInfos.getFirst();
+        }
+
+        mCallback.onSessionUpdated(this, sessionInfo, packageNamesWithRoutingSessionOverrides);
+    }
+
+    private void onSessionOverrideUpdated(RoutingSessionInfo sessionInfo) {
+        // TODO: b/362507305 - Consider adding routes from other provider services. This is not a
+        // trivial change because a provider1-route to provider2-route transfer has seemingly two
+        // possible approachies. Either we first release the current session and then create the new
+        // one, in which case the audio is briefly going to leak through the system route. On the
+        // other hand, if we first create the provider2 session, then there will be a period during
+        // which there will be two overlapping routing policies asking for the exact same media
+        // stream.
+        var builder = new RoutingSessionInfo.Builder(sessionInfo);
+        mLastSystemProviderInfo.getRoutes().stream()
+                .map(MediaRoute2Info::getOriginalId)
+                .forEach(builder::addTransferableRoute);
+        mCallback.onSessionUpdated(
+                /* provider= */ this,
+                builder.build(),
+                /* packageNamesWithRoutingSessionOverrides= */ Set.of());
+    }
+
+    /**
+     * Equivalent to {@link #asSystemRouteId}, except it takes a unique route id instead of a
+     * original id.
+     */
+    private static String uniqueIdAsSystemRouteId(String providerId, String uniqueRouteId) {
+        return asSystemRouteId(providerId, MediaRouter2Utils.getOriginalId(uniqueRouteId));
+    }
+
+    /**
+     * Returns a unique {@link MediaRoute2Info#getOriginalId() original id} for this provider to
+     * publish system media routes from {@link MediaRoute2ProviderService provider services}.
+     *
+     * <p>This provider will publish system media routes as part of the system routing session.
+     * However, said routes may also support {@link MediaRoute2Info#FLAG_ROUTING_TYPE_REMOTE remote
+     * routing}, meaning we cannot use the same id, or there would be an id collision. As a result,
+     * we derive a {@link MediaRoute2Info#getOriginalId original id} that is unique among all
+     * original route ids used by this provider.
+     */
+    private static String asSystemRouteId(String providerId, String originalRouteId) {
+        return ROUTE_ID_PREFIX_SYSTEM
+                + ROUTE_ID_SYSTEM_SEPARATOR
+                + providerId
+                + ROUTE_ID_SYSTEM_SEPARATOR
+                + originalRouteId;
     }
 
     /**
@@ -145,14 +373,69 @@
      * @param mProxy The corresponding {@link MediaRoute2ProviderServiceProxy}.
      * @param mSystemMediaRoutes The last snapshot of routes from the service that support system
      *     media routing, as defined by {@link MediaRoute2Info#supportsSystemMediaRouting()}.
+     * @param mNewOriginalIdToSourceOriginalIdMap Maps the {@link #mSystemMediaRoutes} ids to the
+     *     original ids of corresponding {@link MediaRoute2ProviderService service} route.
      */
     private record ProviderProxyRecord(
             MediaRoute2ProviderServiceProxy mProxy,
-            Collection<MediaRoute2Info> mSystemMediaRoutes) {
+            Map<String, MediaRoute2Info> mSystemMediaRoutes,
+            Map<String, String> mNewOriginalIdToSourceOriginalIdMap) {
 
         /** Returns a stream representation of the {@link #mSystemMediaRoutes}. */
         public Stream<MediaRoute2Info> getRoutesStream() {
-            return mSystemMediaRoutes.stream();
+            return mSystemMediaRoutes.values().stream();
+        }
+
+        @Nullable
+        public MediaRoute2Info getRouteByOriginalId(String routeOriginalId) {
+            return mSystemMediaRoutes.get(routeOriginalId);
+        }
+
+        /**
+         * Requests the creation of a system media routing session.
+         *
+         * @param requestId The request id.
+         * @param uid The uid of the package whose media to route, or {@link Process#INVALID_UID} if
+         *     not applicable.
+         * @param packageName The name of the package whose media to route.
+         * @param originalRouteId The {@link MediaRoute2Info#getOriginalId() original route id} of
+         *     the route that should be initially selected.
+         * @param callback A {@link MediaRoute2ProviderServiceProxy.SystemMediaSessionCallback} for
+         *     events.
+         * @see MediaRoute2ProviderService#onCreateSystemRoutingSession
+         */
+        public void requestCreateSystemMediaSession(
+                long requestId,
+                int uid,
+                String packageName,
+                String originalRouteId,
+                SystemMediaSessionCallback callback) {
+            var targetRouteId = mNewOriginalIdToSourceOriginalIdMap.get(originalRouteId);
+            if (targetRouteId == null) {
+                Log.w(
+                        TAG,
+                        "Failed system media session creation due to lack of mapping for id: "
+                                + originalRouteId);
+                callback.onRequestFailed(
+                        requestId, MediaRoute2ProviderService.REASON_ROUTE_NOT_AVAILABLE);
+            } else {
+                mProxy.requestCreateSystemMediaSession(
+                        requestId,
+                        uid,
+                        packageName,
+                        targetRouteId,
+                        /* sessionHints= */ null,
+                        callback);
+            }
+        }
+
+        public void requestTransfer(String sessionId, MediaRoute2Info targetRoute) {
+            // TODO: Map the target route to the source route original id.
+            throw new UnsupportedOperationException("TODO Implement");
+        }
+
+        public void releaseSession(long requestId, String originalSessionId) {
+            mProxy.releaseSession(requestId, originalSessionId);
         }
 
         /**
@@ -165,22 +448,177 @@
             if (providerInfo == null) {
                 return null;
             }
-            ArraySet<MediaRoute2Info> routes = new ArraySet<>();
-            providerInfo.getRoutes().stream()
-                    .filter(MediaRoute2Info::supportsSystemMediaRouting)
-                    .forEach(
-                            route -> {
-                                String id =
-                                        ROUTE_ID_PREFIX_SYSTEM
-                                                + route.getProviderId()
-                                                + ROUTE_ID_SYSTEM_SEPARATOR
-                                                + route.getOriginalId();
-                                routes.add(
-                                        new MediaRoute2Info.Builder(id, route.getName())
-                                                .addFeature(FEATURE_LIVE_AUDIO)
-                                                .build());
-                            });
-            return new ProviderProxyRecord(serviceProxy, Collections.unmodifiableSet(routes));
+            Map<String, MediaRoute2Info> routesMap = new ArrayMap<>();
+            Map<String, String> idMap = new ArrayMap<>();
+            for (MediaRoute2Info sourceRoute : providerInfo.getRoutes()) {
+                if (!sourceRoute.supportsSystemMediaRouting()) {
+                    continue;
+                }
+                String id =
+                        asSystemRouteId(providerInfo.getUniqueId(), sourceRoute.getOriginalId());
+                var newRoute =
+                        new MediaRoute2Info.Builder(id, sourceRoute.getName())
+                                .addFeature(FEATURE_LIVE_AUDIO)
+                                .build();
+                routesMap.put(id, newRoute);
+                idMap.put(id, sourceRoute.getOriginalId());
+            }
+            return new ProviderProxyRecord(
+                    serviceProxy,
+                    Collections.unmodifiableMap(routesMap),
+                    Collections.unmodifiableMap(idMap));
+        }
+    }
+
+    private class SystemMediaSessionCallbackImpl implements SystemMediaSessionCallback {
+
+        private final String mProviderId;
+        private final long mRequestId;
+        private final String mClientPackageName;
+        // Accessed only on mHandler.
+        @Nullable private SystemMediaSessionRecord mSessionRecord;
+
+        private SystemMediaSessionCallbackImpl(
+                String providerId, long requestId, String clientPackageName) {
+            mProviderId = providerId;
+            mRequestId = requestId;
+            mClientPackageName = clientPackageName;
+        }
+
+        @Override
+        public void onSessionUpdate(@NonNull RoutingSessionInfo sessionInfo) {
+            mHandler.post(
+                    () -> {
+                        if (mSessionRecord != null) {
+                            mSessionRecord.onSessionUpdate(sessionInfo);
+                        }
+                        SystemMediaSessionRecord systemMediaSessionRecord =
+                                new SystemMediaSessionRecord(mProviderId, sessionInfo);
+                        RoutingSessionInfo translatedSession;
+                        synchronized (mLock) {
+                            mSessionRecord = systemMediaSessionRecord;
+                            mPackageNameToSessionRecord.put(
+                                    mClientPackageName, systemMediaSessionRecord);
+                            mPendingSessionCreations.remove(mRequestId);
+                            translatedSession = systemMediaSessionRecord.mTranslatedSessionInfo;
+                        }
+                        onSessionOverrideUpdated(translatedSession);
+                    });
+        }
+
+        @Override
+        public void onRequestFailed(long requestId, @Reason int reason) {
+            mHandler.post(
+                    () -> {
+                        if (mSessionRecord != null) {
+                            mSessionRecord.onRequestFailed(requestId, reason);
+                        }
+                        synchronized (mLock) {
+                            mPendingSessionCreations.remove(mRequestId);
+                        }
+                        notifyRequestFailed(requestId, reason);
+                    });
+        }
+
+        @Override
+        public void onSessionReleased() {
+            mHandler.post(
+                    () -> {
+                        if (mSessionRecord != null) {
+                            mSessionRecord.onSessionReleased();
+                        } else {
+                            // Should never happen. The session hasn't yet been created.
+                            throw new IllegalStateException();
+                        }
+                    });
+        }
+    }
+
+    private class SystemMediaSessionRecord implements SystemMediaSessionCallback {
+
+        private final String mProviderId;
+
+        @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+        @NonNull
+        private RoutingSessionInfo mSourceSessionInfo;
+
+        /**
+         * The same as {@link #mSourceSessionInfo}, except ids are {@link #asSystemRouteId system
+         * provider ids}.
+         */
+        @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+        @NonNull
+        private RoutingSessionInfo mTranslatedSessionInfo;
+
+        SystemMediaSessionRecord(
+                @NonNull String providerId, @NonNull RoutingSessionInfo sessionInfo) {
+            mProviderId = providerId;
+            mSourceSessionInfo = sessionInfo;
+            mTranslatedSessionInfo = asSystemProviderSession(sessionInfo);
+        }
+
+        @Override
+        public void onSessionUpdate(@NonNull RoutingSessionInfo sessionInfo) {
+            RoutingSessionInfo translatedSessionInfo = mTranslatedSessionInfo;
+            synchronized (mLock) {
+                mSourceSessionInfo = sessionInfo;
+                mTranslatedSessionInfo = asSystemProviderSession(sessionInfo);
+            }
+            onSessionOverrideUpdated(translatedSessionInfo);
+        }
+
+        @Override
+        public void onRequestFailed(long requestId, @Reason int reason) {
+            notifyRequestFailed(requestId, reason);
+        }
+
+        @Override
+        public void onSessionReleased() {
+            synchronized (mLock) {
+                removeSelfFromSessionMap();
+            }
+            notifyGlobalSessionInfoUpdated();
+        }
+
+        @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+        @Nullable
+        public ProviderProxyRecord getProxyRecord() {
+            ProviderProxyRecord provider = mProxyRecords.get(mProviderId);
+            if (provider == null) {
+                // Unexpected condition where the proxy is no longer available while there's an
+                // ongoing session. Could happen due to a crash in the provider process.
+                removeSelfFromSessionMap();
+            }
+            return provider;
+        }
+
+        @GuardedBy("SystemMediaRoute2Provider2.this.mLock")
+        private void removeSelfFromSessionMap() {
+            mPackageNameToSessionRecord.remove(mSourceSessionInfo.getClientPackageName());
+        }
+
+        private RoutingSessionInfo asSystemProviderSession(RoutingSessionInfo session) {
+            var builder =
+                    new RoutingSessionInfo.Builder(session)
+                            .setProviderId(mUniqueId)
+                            .setSystemSession(true)
+                            .clearSelectedRoutes()
+                            .clearSelectableRoutes()
+                            .clearDeselectableRoutes()
+                            .clearTransferableRoutes();
+            session.getSelectedRoutes().stream()
+                    .map(it -> uniqueIdAsSystemRouteId(session.getProviderId(), it))
+                    .forEach(builder::addSelectedRoute);
+            session.getSelectableRoutes().stream()
+                    .map(it -> uniqueIdAsSystemRouteId(session.getProviderId(), it))
+                    .forEach(builder::addSelectableRoute);
+            session.getDeselectableRoutes().stream()
+                    .map(it -> uniqueIdAsSystemRouteId(session.getProviderId(), it))
+                    .forEach(builder::addDeselectableRoute);
+            session.getTransferableRoutes().stream()
+                    .map(it -> uniqueIdAsSystemRouteId(session.getProviderId(), it))
+                    .forEach(builder::addTransferableRoute);
+            return builder.build();
         }
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 89902f7..7cbbe29 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -101,4 +101,10 @@
     void onNotificationFeedbackReceived(String key, Bundle feedback);
 
     void prepareForPossibleShutdown();
+
+    /**
+     *  Called when the notification should be unbundled.
+     * @param key the notification key
+     */
+    void unbundleNotification(String key);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c6d7fc7..7375a68 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -112,6 +112,7 @@
 import static android.service.notification.Flags.callstyleCallbackApi;
 import static android.service.notification.Flags.notificationClassification;
 import static android.service.notification.Flags.notificationForceGrouping;
+import static android.service.notification.Flags.notificationRegroupOnClassification;
 import static android.service.notification.Flags.redactSensitiveNotificationsBigTextStyle;
 import static android.service.notification.Flags.redactSensitiveNotificationsFromUntrustedListeners;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
@@ -1851,6 +1852,42 @@
             }
         }
 
+        @Override
+        public void unbundleNotification(String key) {
+            if (!(notificationClassification() && notificationRegroupOnClassification())) {
+                return;
+            }
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r == null) {
+                    return;
+                }
+
+                if (DBG) {
+                    Slog.v(TAG, "unbundleNotification: " + r);
+                }
+
+                boolean hasOriginalSummary = false;
+                if (r.getSbn().isAppGroup() && r.getNotification().isGroupChild()) {
+                    final String oldGroupKey = GroupHelper.getFullAggregateGroupKey(
+                            r.getSbn().getPackageName(), r.getOriginalGroupKey(), r.getUserId());
+                    NotificationRecord groupSummary = mSummaryByGroupKey.get(oldGroupKey);
+                    // We only care about app-provided valid groups
+                    hasOriginalSummary = (groupSummary != null
+                            && !GroupHelper.isAggregatedGroup(groupSummary));
+                }
+
+                // Only NotificationRecord's mChannel is updated when bundled, the Notification
+                // mChannelId will always be the original channel.
+                String origChannelId = r.getNotification().getChannelId();
+                NotificationChannel originalChannel = mPreferencesHelper.getNotificationChannel(
+                        r.getSbn().getPackageName(), r.getUid(), origChannelId, false);
+                if (originalChannel != null && !origChannelId.equals(r.getChannel().getId())) {
+                    r.updateNotificationChannel(originalChannel);
+                    mGroupHelper.onNotificationUnbundled(r, hasOriginalSummary);
+                }
+            }
+        }
     };
 
     NotificationManagerPrivate mNotificationManagerPrivate = new NotificationManagerPrivate() {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 749952e..15377d6 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -559,7 +559,7 @@
 
             if (r.uid == UNKNOWN_UID) {
                 if (Flags.persistIncompleteRestoreData()) {
-                    r.userId = userId;
+                    r.userIdWhenUidUnknown = userId;
                 }
                 mRestoredWithoutUids.put(unrestoredPackageKey(pkg, userId), r);
             } else {
@@ -756,7 +756,7 @@
 
         if (Flags.persistIncompleteRestoreData() && r.uid == UNKNOWN_UID) {
             out.attributeLong(null, ATT_CREATION_TIME, r.creationTime);
-            out.attributeInt(null, ATT_USERID, r.userId);
+            out.attributeInt(null, ATT_USERID, r.userIdWhenUidUnknown);
         }
 
         if (!forBackup) {
@@ -1959,7 +1959,7 @@
         ArrayList<ZenBypassingApp> bypassing = new ArrayList<>();
         synchronized (mLock) {
             for (PackagePreferences p : mPackagePreferences.values()) {
-                if (p.userId != userId) {
+                if (UserHandle.getUserId(p.uid) != userId) {
                     continue;
                 }
                 int totalChannelCount = p.channels.size();
@@ -3189,7 +3189,7 @@
         // Until we enable the UI, we should return false.
         boolean canHavePromotedNotifs = android.app.Flags.uiRichOngoing();
 
-        @UserIdInt int userId;
+        @UserIdInt int userIdWhenUidUnknown;
 
         Delegate delegate = null;
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 3528d3d..8a35006 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -487,6 +487,20 @@
     ProviderInfo resolveContentProvider(@NonNull String name,
             @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId, int callingUid);
 
+    /**
+     * Resolves a ContentProvider on behalf of a UID
+     * @param name Authority of the content provider
+     * @param flags option flags to modify the data returned.
+     * @param userId Current user ID
+     * @param filterCallingUid UID of the caller who's access to the content provider
+     *        is to be checked
+     * @return
+     */
+    @Nullable
+    ProviderInfo resolveContentProviderForUid(@NonNull String name,
+            @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId,
+            int filterCallingUid);
+
     @Nullable
     ProviderInfo getGrantImplicitAccessProviderInfo(int recipientUid,
             @NonNull String visibleAuthority);
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index be2f58d..3861762 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -4749,6 +4749,38 @@
 
     @Nullable
     @Override
+    public ProviderInfo resolveContentProviderForUid(@NonNull String name,
+            @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId,
+            int filterCallingUid) {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.RESOLVE_COMPONENT_FOR_UID,
+                "resolveContentProviderForUid");
+
+        int callingUid = Binder.getCallingUid();
+        int filterUserId = UserHandle.getUserId(filterCallingUid);
+        enforceCrossUserPermission(callingUid, filterUserId, false, false,
+                "resolveContentProviderForUid");
+
+        // Real callingUid should be able to see filterCallingUid
+        if (filterAppAccess(filterCallingUid, callingUid)) {
+            return null;
+        }
+
+        ProviderInfo pInfo = resolveContentProvider(name, flags, userId, filterCallingUid);
+        if (pInfo == null) {
+            return null;
+        }
+        // Real callingUid should be able to see the ContentProvider accessible to filterCallingUid
+        ProviderInfo pInfo2 = resolveContentProvider(name, flags, userId, callingUid);
+        if (pInfo2 != null
+                && Objects.equals(pInfo.name, pInfo2.name)
+                && Objects.equals(pInfo.authority, pInfo2.authority)) {
+            return pInfo;
+        }
+        return null;
+    }
+
+    @Nullable
+    @Override
     public ProviderInfo resolveContentProvider(@NonNull String name,
             @PackageManager.ResolveInfoFlagsBits long flags, @UserIdInt int userId,
             int callingUid) {
diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java
index f05c54d..b11d349 100644
--- a/services/core/java/com/android/server/pm/IPackageManagerBase.java
+++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java
@@ -1129,6 +1129,12 @@
     }
 
     @Override
+    public final ProviderInfo resolveContentProviderForUid(String name,
+            @PackageManager.ResolveInfoFlagsBits long flags, int userId, int filterCallingUid) {
+        return snapshot().resolveContentProviderForUid(name, flags, userId, filterCallingUid);
+    }
+
+    @Override
     @Deprecated
     public final void resetApplicationPreferences(int userId) {
         mPreferredActivityHelper.resetApplicationPreferences(userId);
diff --git a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java
index e9cb279..e989d68 100644
--- a/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java
+++ b/services/core/java/com/android/server/pm/permission/AccessCheckDelegate.java
@@ -40,7 +40,7 @@
 import com.android.internal.util.function.DodecFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
-import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.NonaFunction;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.TriFunction;
 import com.android.internal.util.function.UndecFunction;
@@ -351,22 +351,22 @@
         @Override
         public SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName,
                 @Nullable String featureId, int virtualDeviceId, boolean shouldCollectAsyncNotedOp,
-                @Nullable String message, boolean shouldCollectMessage,
-                @NonNull OctFunction<Integer, Integer, String, String, Integer, Boolean, String,
-                        Boolean, SyncNotedAppOp> superImpl) {
+                @Nullable String message, boolean shouldCollectMessage, int notedCount,
+                @NonNull NonaFunction<Integer, Integer, String, String, Integer, Boolean, String,
+                                        Boolean, Integer, SyncNotedAppOp> superImpl) {
             if (uid == mDelegateAndOwnerUid && isDelegateOp(code)) {
                 final int shellUid = UserHandle.getUid(UserHandle.getUserId(uid),
                         Process.SHELL_UID);
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return superImpl.apply(code, shellUid, SHELL_PKG, featureId, virtualDeviceId,
-                            shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                            shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount);
                 } finally {
                     Binder.restoreCallingIdentity(identity);
                 }
             }
             return superImpl.apply(code, uid, packageName, featureId, virtualDeviceId,
-                    shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                    shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index 3f9144f..dea52fd 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -53,7 +53,7 @@
 import com.android.internal.util.function.DodecFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
-import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.NonaFunction;
 import com.android.internal.util.function.QuadFunction;
 import com.android.internal.util.function.UndecFunction;
 import com.android.server.LocalServices;
@@ -248,11 +248,12 @@
     public SyncNotedAppOp noteOperation(int code, int uid, @Nullable String packageName,
             @Nullable String attributionTag, int virtualDeviceId,
             boolean shouldCollectAsyncNotedOp, @Nullable String message,
-            boolean shouldCollectMessage, @NonNull OctFunction<Integer, Integer, String, String,
-                    Integer, Boolean, String, Boolean, SyncNotedAppOp> superImpl) {
+            boolean shouldCollectMessage, int notedCount,
+            @NonNull NonaFunction<Integer, Integer, String, String,
+                    Integer, Boolean, String, Boolean, Integer, SyncNotedAppOp> superImpl) {
         return superImpl.apply(resolveDatasourceOp(code, uid, packageName, attributionTag),
                 resolveUid(code, uid), packageName, attributionTag, virtualDeviceId,
-                shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+                shouldCollectAsyncNotedOp, message, shouldCollectMessage, notedCount);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c4d1cc7..5ab5965 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -88,7 +88,9 @@
 import static com.android.hardware.input.Flags.inputManagerLifecycleSupport;
 import static com.android.hardware.input.Flags.keyboardA11yShortcutControl;
 import static com.android.hardware.input.Flags.modifierShortcutDump;
+import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
 import static com.android.hardware.input.Flags.useKeyGestureEventHandler;
+import static com.android.server.GestureLauncherService.DOUBLE_POWER_TAP_COUNT_THRESHOLD;
 import static com.android.server.flags.Flags.modifierShortcutManagerMultiuser;
 import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
@@ -191,7 +193,7 @@
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.speech.RecognizerIntent;
 import android.telecom.TelecomManager;
-import android.util.ArraySet;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.MutableBoolean;
@@ -432,6 +434,16 @@
             "android.intent.action.VOICE_ASSIST_RETAIL";
 
     /**
+     * Maximum amount of time in milliseconds between consecutive power onKeyDown events to be
+     * considered a multi-press, only used for the power button.
+     * Note: To maintain backwards compatibility for the power button, we are measuring the times
+     * between consecutive down events instead of the first tap's up event and the second tap's
+     * down event.
+     */
+    @VisibleForTesting public static final int POWER_MULTI_PRESS_TIMEOUT_MILLIS =
+            ViewConfiguration.getMultiPressTimeout();
+
+    /**
      * Lock protecting internal state.  Must not call out into window
      * manager with lock held.  (This lock will be acquired in places
      * where the window manager is calling in with its own lock held.)
@@ -492,6 +504,32 @@
 
     private WindowWakeUpPolicy mWindowWakeUpPolicy;
 
+    /**
+     * The three variables below are used for custom power key gesture detection in
+     * PhoneWindowManager. They are used to detect when the power button has been double pressed
+     * and, when it does happen, makes the behavior overrideable by the app.
+     *
+     * We cannot use the {@link PowerKeyRule} for this because multi-press power gesture detection
+     * and behaviors are handled by {@link com.android.server.GestureLauncherService}, and the
+     * {@link PowerKeyRule} only handles single and long-presses of the power button. As a result,
+     * overriding the double tap behavior requires custom gesture detection here that mimics the
+     * logic in {@link com.android.server.GestureLauncherService}.
+     *
+     * Long-term, it would be beneficial to move all power gesture detection to
+     * {@link PowerKeyRule} so that this custom logic isn't required.
+     */
+    // Time of last power down event.
+    private long mLastPowerDown;
+
+    // Number of power button events consecutively triggered (within a specific timeout threshold).
+    private int mPowerButtonConsecutiveTaps = 0;
+
+    // Whether a double tap of the power button has been detected.
+    volatile boolean mDoubleTapPowerDetected;
+
+    // Runnable that is queued on a delay when the first power keyDown event is sent to the app.
+    private Runnable mPowerKeyDelayedRunnable = null;
+
     boolean mSafeMode;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
@@ -725,23 +763,6 @@
 
     private final boolean mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled();
 
-    // Key codes that should be ignored for visible background users in MUMD environment.
-    private static final Set<Integer> KEY_CODES_IGNORED_FOR_VISIBLE_BACKGROUND_USERS =
-            new ArraySet<>(Arrays.asList(
-                    KeyEvent.KEYCODE_POWER,
-                    KeyEvent.KEYCODE_SLEEP,
-                    KeyEvent.KEYCODE_WAKEUP,
-                    KeyEvent.KEYCODE_CALL,
-                    KeyEvent.KEYCODE_ENDCALL,
-                    KeyEvent.KEYCODE_ASSIST,
-                    KeyEvent.KEYCODE_VOICE_ASSIST,
-                    KeyEvent.KEYCODE_MUTE,
-                    KeyEvent.KEYCODE_VOLUME_MUTE,
-                    KeyEvent.KEYCODE_RECENT_APPS,
-                    KeyEvent.KEYCODE_APP_SWITCH,
-                    KeyEvent.KEYCODE_NOTIFICATION
-            ));
-
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
     private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
@@ -1097,6 +1118,11 @@
         mPowerKeyHandled = mPowerKeyHandled || hungUp
                 || handledByPowerManager || isKeyGestureTriggered
                 || mKeyCombinationManager.isPowerKeyIntercepted();
+
+        if (overridePowerKeyBehaviorInFocusedWindow()) {
+            mPowerKeyHandled |= mDoubleTapPowerDetected;
+        }
+
         if (!mPowerKeyHandled) {
             if (!interactive) {
                 wakeUpFromWakeKey(event);
@@ -2669,7 +2695,18 @@
             if (mShouldEarlyShortPressOnPower) {
                 return;
             }
-            powerPress(downTime, 1 /*count*/, displayId);
+            // TODO(b/380433365): Remove deferring single power press action when refactoring.
+            if (overridePowerKeyBehaviorInFocusedWindow()) {
+                mDeferredKeyActionExecutor.cancelQueuedAction(KEYCODE_POWER);
+                mDeferredKeyActionExecutor.queueKeyAction(
+                        KEYCODE_POWER,
+                        downTime,
+                        () -> {
+                            powerPress(downTime, 1 /*count*/, displayId);
+                        });
+            } else {
+                powerPress(downTime, 1 /*count*/, displayId);
+            }
         }
 
         @Override
@@ -2700,7 +2737,17 @@
 
         @Override
         void onMultiPress(long downTime, int count, int displayId) {
-            powerPress(downTime, count, displayId);
+            if (overridePowerKeyBehaviorInFocusedWindow()) {
+                mDeferredKeyActionExecutor.cancelQueuedAction(KEYCODE_POWER);
+                mDeferredKeyActionExecutor.queueKeyAction(
+                        KEYCODE_POWER,
+                        downTime,
+                        () -> {
+                            powerPress(downTime, count, displayId);
+                        });
+            } else {
+                powerPress(downTime, count, displayId);
+            }
         }
 
         @Override
@@ -3477,6 +3524,12 @@
             }
         }
 
+        if (overridePowerKeyBehaviorInFocusedWindow() && event.getKeyCode() == KEYCODE_POWER
+                && event.getAction() == KeyEvent.ACTION_UP
+                && mDoubleTapPowerDetected) {
+            mDoubleTapPowerDetected = false;
+        }
+
         return needToConsumeKey ? keyConsumed : keyNotConsumed;
     }
 
@@ -3992,6 +4045,8 @@
                     sendSystemKeyToStatusBarAsync(event);
                     return true;
                 }
+            case KeyEvent.KEYCODE_POWER:
+                return interceptPowerKeyBeforeDispatching(focusedToken, event);
             case KeyEvent.KEYCODE_SCREENSHOT:
                 if (firstDown) {
                     interceptScreenshotChord(SCREENSHOT_KEY_OTHER, 0 /*pressDelay*/);
@@ -4047,6 +4102,8 @@
                     sendSystemKeyToStatusBarAsync(event);
                     return true;
                 }
+            case KeyEvent.KEYCODE_POWER:
+                return interceptPowerKeyBeforeDispatching(focusedToken, event);
         }
         if (isValidGlobalKey(keyCode)
                 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
@@ -4057,6 +4114,90 @@
         return (metaState & KeyEvent.META_META_ON) != 0;
     }
 
+    /**
+     * Called by interceptKeyBeforeDispatching to handle interception logic for KEYCODE_POWER
+     * KeyEvents.
+     *
+     * @return true if intercepting the key, false if sending to app.
+     */
+    private boolean interceptPowerKeyBeforeDispatching(IBinder focusedToken, KeyEvent event) {
+        if (!overridePowerKeyBehaviorInFocusedWindow()) {
+            //Flag disabled: intercept the power key and do not send to app.
+            return true;
+        }
+        if (event.getKeyCode() != KEYCODE_POWER) {
+            Log.wtf(TAG, "interceptPowerKeyBeforeDispatching received a non-power KeyEvent "
+                    + "with key code: " + event.getKeyCode());
+            return false;
+        }
+
+        // Intercept keys (don't send to app) for 3x, 4x, 5x gestures)
+        if (mPowerButtonConsecutiveTaps > DOUBLE_POWER_TAP_COUNT_THRESHOLD) {
+            setDeferredKeyActionsExecutableAsync(KEYCODE_POWER, event.getDownTime());
+            return true;
+        }
+
+        // UP key; just reuse the original decision.
+        if (event.getAction() == KeyEvent.ACTION_UP) {
+            final Set<Integer> consumedKeys = mConsumedKeysForDevice.get(event.getDeviceId());
+            return consumedKeys != null
+                    && consumedKeys.contains(event.getKeyCode());
+        }
+
+        KeyInterceptionInfo info =
+                mWindowManagerInternal.getKeyInterceptionInfoFromToken(focusedToken);
+
+        if (info == null || !mButtonOverridePermissionChecker.canWindowOverridePowerKey(mContext,
+                info.windowOwnerUid, info.inputFeaturesFlags)) {
+            // The focused window does not have the permission to override power key behavior.
+            if (DEBUG_INPUT) {
+                String interceptReason = "";
+                if (info == null) {
+                    interceptReason = "Window is null";
+                } else if (!mButtonOverridePermissionChecker.canAppOverrideSystemKey(mContext,
+                        info.windowOwnerUid)) {
+                    interceptReason = "Application does not have "
+                            + "OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW permission";
+                } else {
+                    interceptReason = "Window does not have inputFeatureFlag set";
+                }
+
+                Log.d(TAG, TextUtils.formatSimple("Intercepting KEYCODE_POWER event. action=%d, "
+                                + "eventTime=%d to window=%s. interceptReason=%s. "
+                                + "mDoubleTapPowerDetected=%b",
+                        event.getAction(), event.getEventTime(), (info != null)
+                                ? info.windowTitle : "null", interceptReason,
+                        mDoubleTapPowerDetected));
+            }
+            // Intercept the key (i.e. do not send to app)
+            setDeferredKeyActionsExecutableAsync(KEYCODE_POWER, event.getDownTime());
+            return true;
+        }
+
+        if (DEBUG_INPUT) {
+            Log.d(TAG, TextUtils.formatSimple("Sending KEYCODE_POWER to app. action=%d, "
+                            + "eventTime=%d to window=%s. mDoubleTapPowerDetected=%b",
+                    event.getAction(), event.getEventTime(), info.windowTitle,
+                    mDoubleTapPowerDetected));
+        }
+
+        if (!mDoubleTapPowerDetected) {
+            //Single press: post a delayed runnable for the single press power action that will be
+            // called if it's not cancelled by a double press.
+            final var downTime = event.getDownTime();
+            mPowerKeyDelayedRunnable = () ->
+                    setDeferredKeyActionsExecutableAsync(KEYCODE_POWER, downTime);
+            mHandler.postDelayed(mPowerKeyDelayedRunnable, POWER_MULTI_PRESS_TIMEOUT_MILLIS);
+        } else if (mPowerKeyDelayedRunnable != null) {
+            //Double press detected: cancel the single press runnable.
+            mHandler.removeCallbacks(mPowerKeyDelayedRunnable);
+            mPowerKeyDelayedRunnable = null;
+        }
+
+        // Focused window has permission. Send to app.
+        return false;
+    }
+
     @SuppressLint("MissingPermission")
     private void initKeyGestures() {
         if (!useKeyGestureEventHandler()) {
@@ -4068,7 +4209,7 @@
                     @Nullable IBinder focusedToken) {
                 boolean handled = PhoneWindowManager.this.handleKeyGestureEvent(event,
                         focusedToken);
-                if (handled && Arrays.stream(event.getKeycodes()).anyMatch(
+                if (handled && !event.isCancelled() && Arrays.stream(event.getKeycodes()).anyMatch(
                         (keycode) -> keycode == KeyEvent.KEYCODE_POWER)) {
                     mPowerKeyHandled = true;
                 }
@@ -4580,6 +4721,11 @@
             return true;
         }
 
+        if (overridePowerKeyBehaviorInFocusedWindow() && keyCode == KEYCODE_POWER) {
+            handleUnhandledSystemKey(event);
+            return true;
+        }
+
         if (useKeyGestureEventHandler()) {
             return false;
         }
@@ -5127,7 +5273,7 @@
         // There are key events that perform the operation as the current user,
         // and these should be ignored for visible background users.
         if (mVisibleBackgroundUsersEnabled
-                && KEY_CODES_IGNORED_FOR_VISIBLE_BACKGROUND_USERS.contains(keyCode)
+                && !KeyEvent.isVisibleBackgroundUserAllowedKey(keyCode)
                 && !isKeyEventForCurrentUser(event.getDisplayId(), keyCode, null)) {
             return 0;
         }
@@ -5414,8 +5560,12 @@
                         KeyEvent.actionToString(event.getAction()),
                         mPowerKeyHandled ? 1 : 0,
                         mSingleKeyGestureDetector.getKeyPressCounter(KeyEvent.KEYCODE_POWER));
-                // Any activity on the power button stops the accessibility shortcut
-                result &= ~ACTION_PASS_TO_USER;
+                if (overridePowerKeyBehaviorInFocusedWindow()) {
+                    result |= ACTION_PASS_TO_USER;
+                } else {
+                    // Any activity on the power button stops the accessibility shortcut
+                    result &= ~ACTION_PASS_TO_USER;
+                }
                 isWakeKey = false; // wake-up will be handled separately
                 if (down) {
                     interceptPowerKeyDown(event, interactiveAndAwake, isKeyGestureTriggered);
@@ -5677,6 +5827,35 @@
         }
 
         if (event.getKeyCode() == KEYCODE_POWER && event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (overridePowerKeyBehaviorInFocusedWindow()) {
+                if (event.getRepeatCount() > 0 && !mHasFeatureWatch) {
+                    return;
+                }
+                if (mGestureLauncherService != null) {
+                    mGestureLauncherService.processPowerKeyDown(event);
+                }
+
+                if (detectDoubleTapPower(event)) {
+                    mDoubleTapPowerDetected = true;
+
+                    // Copy of the event for handler in case the original event gets recycled.
+                    KeyEvent eventCopy = KeyEvent.obtain(event);
+                    mDeferredKeyActionExecutor.queueKeyAction(
+                            KeyEvent.KEYCODE_POWER,
+                            eventCopy.getEventTime(),
+                            () -> {
+                                if (!handleCameraGesture(eventCopy, interactive)) {
+                                    mSingleKeyGestureDetector.interceptKey(
+                                            eventCopy, interactive, defaultDisplayOn);
+                                } else {
+                                    mSingleKeyGestureDetector.reset();
+                                }
+                                eventCopy.recycle();
+                            });
+                    return;
+                }
+            }
+
             mPowerKeyHandled = handleCameraGesture(event, interactive);
             if (mPowerKeyHandled) {
                 // handled by camera gesture.
@@ -5688,6 +5867,26 @@
         mSingleKeyGestureDetector.interceptKey(event, interactive, defaultDisplayOn);
     }
 
+    private boolean detectDoubleTapPower(KeyEvent event) {
+        //Watches use the SingleKeyGestureDetector for detecting multi-press gestures.
+        if (mHasFeatureWatch || event.getKeyCode() != KEYCODE_POWER
+                || event.getAction() != KeyEvent.ACTION_DOWN  || event.getRepeatCount() != 0) {
+            return false;
+        }
+
+        final long powerTapInterval = event.getEventTime() - mLastPowerDown;
+        mLastPowerDown = event.getEventTime();
+        if (powerTapInterval >= POWER_MULTI_PRESS_TIMEOUT_MILLIS) {
+            // Tap too slow for double press
+            mPowerButtonConsecutiveTaps = 1;
+        } else {
+            mPowerButtonConsecutiveTaps++;
+        }
+
+        return powerTapInterval < POWER_MULTI_PRESS_TIMEOUT_MILLIS
+                && mPowerButtonConsecutiveTaps == DOUBLE_POWER_TAP_COUNT_THRESHOLD;
+    }
+
     // The camera gesture will be detected by GestureLauncherService.
     private boolean handleCameraGesture(KeyEvent event, boolean interactive) {
         // camera gesture.
@@ -7544,6 +7743,12 @@
                     null)
                     == PERMISSION_GRANTED;
         }
+
+        boolean canWindowOverridePowerKey(Context context, int uid, int inputFeaturesFlags) {
+            return canAppOverrideSystemKey(context, uid)
+                    && (inputFeaturesFlags & WindowManager.LayoutParams
+                    .INPUT_FEATURE_RECEIVE_POWER_KEY_DOUBLE_PRESS) != 0;
+        }
     }
 
     private int getTargetDisplayIdForKeyEvent(KeyEvent event) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 0c3c46c..102dc07 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -37,11 +37,14 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IWakeLockCallback;
+import android.os.IScreenTimeoutPolicyListener;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
+import android.os.PowerManager.ScreenTimeoutPolicy;
 import android.os.PowerManagerInternal;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -52,6 +55,7 @@
 import android.os.WorkSource.WorkChain;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -152,6 +156,11 @@
     private final Intent mScreenOffIntent;
     private final Bundle mScreenOnOffOptions;
 
+    // Display id -> ScreenTimeoutPolicyListenersContainer that contains list of screen
+    // wake lock listeners
+    private final SparseArray<ScreenTimeoutPolicyListenersContainer> mScreenTimeoutPolicyListeners
+            = new SparseArray<>();
+
     // True if the device should suspend when the screen is off due to proximity.
     private final boolean mSuspendWhenScreenOffDueToProximityConfig;
 
@@ -479,6 +488,7 @@
             case PowerManager.PARTIAL_WAKE_LOCK:
                 return BatteryStats.WAKE_TYPE_PARTIAL;
 
+            case PowerManager.FULL_WAKE_LOCK:
             case PowerManager.SCREEN_DIM_WAKE_LOCK:
             case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                 return BatteryStats.WAKE_TYPE_FULL;
@@ -503,6 +513,31 @@
         }
     }
 
+    @VisibleForTesting
+    int getWakelockMonitorTypeForLogging(int flags) {
+        switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+            case PowerManager.FULL_WAKE_LOCK, PowerManager.SCREEN_DIM_WAKE_LOCK,
+                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                return PowerManager.FULL_WAKE_LOCK;
+            case PowerManager.DRAW_WAKE_LOCK:
+                return PowerManager.DRAW_WAKE_LOCK;
+            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                if (mSuspendWhenScreenOffDueToProximityConfig) {
+                    return -1;
+                }
+                return PowerManager.PARTIAL_WAKE_LOCK;
+            case PowerManager.PARTIAL_WAKE_LOCK:
+                return PowerManager.PARTIAL_WAKE_LOCK;
+            case PowerManager.DOZE_WAKE_LOCK:
+                // Doze wake locks are an internal implementation detail of the
+                // communication between dream manager service and power manager
+                // service.  They have no additive battery impact.
+                return -1;
+            default:
+                return -1;
+        }
+    }
+
     /**
      * Notifies that the device is changing wakefulness.
      * This function may be called even if the previous change hasn't finished in
@@ -1244,6 +1279,146 @@
         }
     }
 
+    /**
+     * Adds a listener for the screen timeout policy
+     * @param displayId display ID
+     * @param screenTimeoutPolicy initial state of the timeout policy
+     * @param listener callback to receive screen timeout policy updates
+     */
+    void addScreenTimeoutPolicyListener(int displayId, @ScreenTimeoutPolicy int screenTimeoutPolicy,
+            IScreenTimeoutPolicyListener listener) {
+        synchronized (mLock) {
+            ScreenTimeoutPolicyListenersContainer listenersContainer =
+                    mScreenTimeoutPolicyListeners.get(displayId);
+            if (listenersContainer == null) {
+                listenersContainer = new ScreenTimeoutPolicyListenersContainer(
+                        screenTimeoutPolicy);
+                mScreenTimeoutPolicyListeners.set(displayId, listenersContainer);
+            }
+
+            listenersContainer.addListener(listener);
+        }
+    }
+
+    /**
+     * Removes a listener for the screen timeout policy
+     * @param displayId display id from which the listener should be removed
+     * @param listener the instance of the listener
+     */
+    void removeScreenTimeoutPolicyListener(int displayId,
+            IScreenTimeoutPolicyListener listener) {
+        synchronized (mLock) {
+            ScreenTimeoutPolicyListenersContainer listenersContainer =
+                    mScreenTimeoutPolicyListeners.get(displayId);
+            if (listenersContainer == null) {
+                return;
+            }
+
+            listenersContainer.removeListener(listener);
+
+            if (listenersContainer.isEmpty()) {
+                mScreenTimeoutPolicyListeners.remove(displayId);
+            }
+        }
+    }
+
+    /**
+     * Clears all screen timeout policy listeners for the specified display id
+     * @param displayId display id from which the listeners should be cleared
+     */
+    void clearScreenTimeoutPolicyListeners(int displayId) {
+        synchronized (mLock) {
+            mScreenTimeoutPolicyListeners.remove(displayId);
+        }
+    }
+
+    /**
+     * Notifies about screen timeout policy changes of the corresponding display group if
+     * it has changed
+     * @param displayGroupId the id of the display group to report
+     * @param screenTimeoutPolicy screen timeout policy
+     */
+    void notifyScreenTimeoutPolicyChanges(int displayGroupId,
+            @ScreenTimeoutPolicy int screenTimeoutPolicy) {
+        synchronized (mLock) {
+            for (int idx = 0; idx < mScreenTimeoutPolicyListeners.size(); idx++) {
+                final int displayId = mScreenTimeoutPolicyListeners.keyAt(idx);
+                if (mDisplayManagerInternal.getGroupIdForDisplay(displayId) == displayGroupId) {
+                    final ScreenTimeoutPolicyListenersContainer container =
+                            mScreenTimeoutPolicyListeners.valueAt(idx);
+                    container.updateScreenTimeoutPolicyAndNotifyIfNeeded(screenTimeoutPolicy);
+                }
+            }
+        }
+    }
+
+    private final class ScreenTimeoutPolicyListenersContainer {
+        private final RemoteCallbackList<IScreenTimeoutPolicyListener> mListeners;
+        private final ArrayMap<IScreenTimeoutPolicyListener, Integer> mLastReportedState =
+                new ArrayMap<>();
+
+        @ScreenTimeoutPolicy
+        private volatile int mScreenTimeoutPolicy;
+
+        ScreenTimeoutPolicyListenersContainer(int screenTimeoutPolicy) {
+            mScreenTimeoutPolicy = screenTimeoutPolicy;
+            mListeners = new RemoteCallbackList<IScreenTimeoutPolicyListener>() {
+                @Override
+                public void onCallbackDied(IScreenTimeoutPolicyListener callbackInterface) {
+                    mLastReportedState.remove(callbackInterface);
+                }
+            };
+        }
+
+        void updateScreenTimeoutPolicyAndNotifyIfNeeded(
+                @ScreenTimeoutPolicy int screenTimeoutPolicy) {
+            mScreenTimeoutPolicy = screenTimeoutPolicy;
+
+            mHandler.post(() -> {
+                for (int i = mListeners.beginBroadcast() - 1; i >= 0; i--) {
+                    final IScreenTimeoutPolicyListener listener = mListeners.getBroadcastItem(i);
+                    notifyListenerIfNeeded(listener);
+                }
+                mListeners.finishBroadcast();
+            });
+        }
+
+        void addListener(IScreenTimeoutPolicyListener listener) {
+            mListeners.register(listener);
+            mHandler.post(() -> notifyListenerIfNeeded(listener));
+        }
+
+        void removeListener(IScreenTimeoutPolicyListener listener) {
+            mListeners.unregister(listener);
+            mLastReportedState.remove(listener);
+        }
+
+        boolean isEmpty() {
+            return mListeners.getRegisteredCallbackCount() == 0;
+        }
+
+        private void notifyListenerIfNeeded(IScreenTimeoutPolicyListener listener) {
+            final int currentScreenTimeoutPolicy = mScreenTimeoutPolicy;
+            final Integer reportedScreenTimeoutPolicy = mLastReportedState.get(listener);
+            final boolean needsReporting = reportedScreenTimeoutPolicy == null
+                    || !reportedScreenTimeoutPolicy.equals(currentScreenTimeoutPolicy);
+
+            if (!needsReporting) return;
+
+            try {
+                listener.onScreenTimeoutPolicyChanged(currentScreenTimeoutPolicy);
+                mLastReportedState.put(listener, currentScreenTimeoutPolicy);
+            } catch (RemoteException e) {
+                // The RemoteCallbackList will take care of removing
+                // the dead object for us.
+                Slog.e(TAG, "Remote exception when notifying screen timeout policy change", e);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Exception when notifying screen timeout policy change", e);
+                removeListener(listener);
+            }
+        }
+    }
+
     private final class NotifierHandler extends Handler {
 
         public NotifierHandler(Looper looper) {
@@ -1288,7 +1463,7 @@
         if (mBatteryStatsInternal == null) {
             return;
         }
-        final int type = flags & PowerManager.WAKE_LOCK_LEVEL_MASK;
+        final int type = getWakelockMonitorTypeForLogging(flags);
         if (workSource == null || workSource.isEmpty()) {
             final int mappedUid = mBatteryStatsInternal.getOwnerUid(ownerUid);
             mFrameworkStatsLogger.wakelockStateChanged(mappedUid, tag, type, eventType);
diff --git a/services/core/java/com/android/server/power/PowerGroup.java b/services/core/java/com/android/server/power/PowerGroup.java
index 01a2045..86eb34c 100644
--- a/services/core/java/com/android/server/power/PowerGroup.java
+++ b/services/core/java/com/android/server/power/PowerGroup.java
@@ -16,6 +16,8 @@
 
 package com.android.server.power;
 
+import static android.os.PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON;
+import static android.os.PowerManager.SCREEN_TIMEOUT_ACTIVE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -34,6 +36,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
 import android.os.PowerManager;
+import android.os.PowerManager.ScreenTimeoutPolicy;
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.os.Trace;
@@ -415,6 +418,12 @@
         return (mWakeLockSummary & (screenOnWakeLockMask)) != 0;
     }
 
+    @ScreenTimeoutPolicy
+    public int getScreenTimeoutPolicy() {
+        return hasWakeLockKeepingScreenOnLocked() ? SCREEN_TIMEOUT_KEEP_DISPLAY_ON
+                : SCREEN_TIMEOUT_ACTIVE;
+    }
+
     public void setWakeLockSummaryLocked(int summary) {
         mWakeLockSummary = summary;
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index ce8dc69..23383a9 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -63,6 +63,7 @@
 import android.hardware.devicestate.DeviceState;
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.display.AmbientDisplayConfiguration;
+import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.power.Boost;
 import android.hardware.power.Mode;
@@ -76,6 +77,7 @@
 import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.IScreenTimeoutPolicyListener;
 import android.os.IWakeLockCallback;
 import android.os.Looper;
 import android.os.Message;
@@ -341,6 +343,7 @@
     private LightsManager mLightsManager;
     private BatteryManagerInternal mBatteryManagerInternal;
     private DisplayManagerInternal mDisplayManagerInternal;
+    private DisplayManager mDisplayManager;
     private IBatteryStats mBatteryStats;
     private WindowManagerPolicy mPolicy;
     private Notifier mNotifier;
@@ -758,6 +761,24 @@
         }
     }
 
+    private final class DisplayListener implements DisplayManager.DisplayListener {
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            mNotifier.clearScreenTimeoutPolicyListeners(displayId);
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+
+        }
+    }
+
     private final class DisplayGroupPowerChangeListener implements
             DisplayManagerInternal.DisplayGroupListener {
 
@@ -1354,6 +1375,7 @@
             mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
             mPolicy = getLocalService(WindowManagerPolicy.class);
             mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
+            mDisplayManager = mContext.getSystemService(DisplayManager.class);
             mAttentionDetector.systemReady(mContext);
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -1373,6 +1395,7 @@
             DisplayGroupPowerChangeListener displayGroupPowerChangeListener =
                     new DisplayGroupPowerChangeListener();
             mDisplayManagerInternal.registerDisplayGroupListener(displayGroupPowerChangeListener);
+            mDisplayManager.registerDisplayListener(new DisplayListener(), mHandler);
 
             if(mDreamManager != null){
                 // This DreamManager method does not acquire a lock, so it should be safe to call.
@@ -2571,7 +2594,10 @@
             // Phase 5: Send notifications, if needed.
             finishWakefulnessChangeIfNeededLocked();
 
-            // Phase 6: Update suspend blocker.
+            // Phase 6: Notify screen timeout policy changes if needed
+            notifyScreenTimeoutPolicyChangesLocked();
+
+            // Phase 7: Update suspend blocker.
             // Because we might release the last suspend blocker here, we need to make sure
             // we finished everything else first!
             updateSuspendBlockerLocked();
@@ -3824,6 +3850,16 @@
                         & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
     }
 
+    @GuardedBy("mLock")
+    private void notifyScreenTimeoutPolicyChangesLocked() {
+        for (int idx = 0; idx < mPowerGroups.size(); idx++) {
+            final int powerGroupId = mPowerGroups.keyAt(idx);
+            final PowerGroup powerGroup = mPowerGroups.valueAt(idx);
+            final int screenTimeoutPolicy = powerGroup.getScreenTimeoutPolicy();
+            mNotifier.notifyScreenTimeoutPolicyChanges(powerGroupId, screenTimeoutPolicy);
+        }
+    }
+
     /**
      * Updates the suspend blocker that keeps the CPU alive.
      *
@@ -5973,6 +6009,55 @@
         }
 
         @Override // Binder call
+        public void addScreenTimeoutPolicyListener(int displayId,
+                IScreenTimeoutPolicyListener listener) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+                    null);
+
+            if (displayId == Display.INVALID_DISPLAY) {
+                throw new IllegalArgumentException("Valid display id is expected");
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                int initialTimeoutPolicy;
+                final int displayGroupId = mDisplayManagerInternal.getGroupIdForDisplay(displayId);
+                synchronized (mLock) {
+                    final PowerGroup powerGroup = mPowerGroups.get(displayGroupId);
+                    if (powerGroup != null) {
+                        initialTimeoutPolicy = powerGroup.getScreenTimeoutPolicy();
+                    } else {
+                        throw new IllegalArgumentException("No display found for the specified "
+                                + "display id " + displayId);
+                    }
+                }
+
+                mNotifier.addScreenTimeoutPolicyListener(displayId, initialTimeoutPolicy,
+                        listener);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void removeScreenTimeoutPolicyListener(int displayId,
+                IScreenTimeoutPolicyListener listener) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+                    null);
+
+            if (displayId == Display.INVALID_DISPLAY) {
+                throw new IllegalArgumentException("Valid display id is expected");
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                mNotifier.removeScreenTimeoutPolicyListener(displayId, listener);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         public void userActivity(int displayId, long eventTime,
                 @PowerManager.UserActivityEvent int event, int flags) {
             final long now = mClock.uptimeMillis();
diff --git a/services/core/java/com/android/server/power/WakefulnessSessionObserver.java b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
index 64f0693..d377c23 100644
--- a/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
+++ b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
@@ -205,6 +205,13 @@
                         UserHandle.USER_ALL);
 
         mPhysicalDisplayPortIdForDefaultDisplay = getPhysicalDisplayPortId(DEFAULT_DISPLAY);
+        registerDisplayListener();
+        mPowerGroups.append(
+                Display.DEFAULT_DISPLAY_GROUP,
+                new WakefulnessSessionPowerGroup(Display.DEFAULT_DISPLAY_GROUP));
+    }
+
+    private void registerDisplayListener() {
         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
         if (displayManager != null) {
             displayManager.registerDisplayListener(
@@ -226,12 +233,8 @@
                         }
                     },
                     mHandler,
-                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED);
+                    DisplayManager.EVENT_TYPE_DISPLAY_CHANGED);
         }
-
-        mPowerGroups.append(
-                Display.DEFAULT_DISPLAY_GROUP,
-                new WakefulnessSessionPowerGroup(Display.DEFAULT_DISPLAY_GROUP));
     }
 
     /**
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index aae7417..c4e4c42 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -20,9 +20,11 @@
 
 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
 import static com.android.server.power.hint.Flags.adpfSessionTag;
+import static com.android.server.power.hint.Flags.cpuHeadroomAffinityCheck;
 import static com.android.server.power.hint.Flags.powerhintThreadCleanup;
 import static com.android.server.power.hint.Flags.resetOnForkEnabled;
 
+import android.Manifest;
 import android.adpf.ISessionManager;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -40,6 +42,7 @@
 import android.hardware.power.GpuHeadroomResult;
 import android.hardware.power.IPower;
 import android.hardware.power.SessionConfig;
+import android.hardware.power.SessionMode;
 import android.hardware.power.SessionTag;
 import android.hardware.power.SupportInfo;
 import android.hardware.power.WorkDuration;
@@ -56,8 +59,12 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.os.SessionCreationConfig;
 import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.system.Os;
+import android.system.OsConstants;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -75,10 +82,12 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
-import com.android.server.power.hint.HintManagerService.AppHintSession.SessionModes;
 import com.android.server.utils.Slogf;
 
+import java.io.BufferedReader;
 import java.io.FileDescriptor;
+import java.io.FileReader;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -94,6 +103,8 @@
 import java.util.TreeMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /** An hint service implementation that runs in System Server process. */
 public final class HintManagerService extends SystemService {
@@ -102,10 +113,10 @@
 
     private static final int EVENT_CLEAN_UP_UID = 3;
     @VisibleForTesting  static final int CLEAN_UP_UID_DELAY_MILLIS = 1000;
-    // The minimum interval between the headroom calls as rate limiting.
-    private static final int DEFAULT_GPU_HEADROOM_INTERVAL_MILLIS = 1000;
-    private static final int DEFAULT_CPU_HEADROOM_INTERVAL_MILLIS = 1000;
 
+    // example: cpu  2255 34 2290 22625563 6290 127 456
+    private static final Pattern PROC_STAT_CPU_TIME_TOTAL_PATTERN =
+            Pattern.compile("cpu\\s+(?<user>[0-9]+)\\s(?<nice>[0-9]+).+");
 
     @VisibleForTesting final long mHintSessionPreferredRate;
 
@@ -191,10 +202,26 @@
     private static final String PROPERTY_HWUI_ENABLE_HINT_MANAGER = "debug.hwui.use_hint_manager";
     private static final String PROPERTY_USE_HAL_HEADROOMS = "persist.hms.use_hal_headrooms";
     private static final String PROPERTY_CHECK_HEADROOM_TID = "persist.hms.check_headroom_tid";
-
+    private static final String PROPERTY_CHECK_HEADROOM_AFFINITY =
+            "persist.hms.check_headroom_affinity";
+    private static final String PROPERTY_CHECK_HEADROOM_PROC_STAT_MIN_MILLIS =
+            "persist.hms.check_headroom_proc_stat_min_millis";
     private Boolean mFMQUsesIntegratedEventFlag = false;
 
     private final Object mCpuHeadroomLock = new Object();
+    @VisibleForTesting
+    final float mJiffyMillis;
+    private final int mCheckHeadroomProcStatMinMillis;
+    @GuardedBy("mCpuHeadroomLock")
+    private long mLastCpuUserModeTimeCheckedMillis = 0;
+    @GuardedBy("mCpuHeadroomLock")
+    private long mLastCpuUserModeJiffies = 0;
+    @GuardedBy("mCpuHeadroomLock")
+    private final Map<Integer, Long> mUidToLastUserModeJiffies;
+    @VisibleForTesting
+    private String mProcStatFilePathOverride = null;
+    @VisibleForTesting
+    private boolean mEnforceCpuHeadroomUserModeCpuTimeCheck = false;
 
     private ISessionManager mSessionManager;
 
@@ -309,8 +336,16 @@
                 new GpuHeadroomParamsInternal().calculationWindowMillis;
         if (mSupportInfo.headroom.isCpuSupported) {
             mCpuHeadroomCache = new HeadroomCache<>(2, mSupportInfo.headroom.cpuMinIntervalMillis);
+            mUidToLastUserModeJiffies = new ArrayMap<>();
+            long jiffyHz = Os.sysconf(OsConstants._SC_CLK_TCK);
+            mJiffyMillis = 1000.0f / jiffyHz;
+            mCheckHeadroomProcStatMinMillis = SystemProperties.getInt(
+                    PROPERTY_CHECK_HEADROOM_PROC_STAT_MIN_MILLIS, 50);
         } else {
             mCpuHeadroomCache = null;
+            mUidToLastUserModeJiffies = null;
+            mJiffyMillis = 0.0f;
+            mCheckHeadroomProcStatMinMillis = 0;
         }
         if (mSupportInfo.headroom.isGpuSupported) {
             mGpuHeadroomCache = new HeadroomCache<>(2, mSupportInfo.headroom.gpuMinIntervalMillis);
@@ -369,6 +404,35 @@
         return supportInfo;
     }
 
+    @VisibleForTesting
+    void setProcStatPathOverride(String override) {
+        mProcStatFilePathOverride = override;
+        mEnforceCpuHeadroomUserModeCpuTimeCheck = true;
+    }
+
+    private boolean tooManyPipelineThreads(int uid) {
+        synchronized (mThreadsUsageObject) {
+            ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(uid);
+            int graphicsPipelineThreadCount = 0;
+            if (threadsSet != null) {
+                // We count the graphics pipeline threads that are
+                // *not* in this session, since those in this session
+                // will be replaced. Then if the count plus the new tids
+                // is over max available graphics pipeline threads we raise
+                // an exception.
+                for (ThreadUsageTracker t : threadsSet) {
+                    if (t.isGraphicsPipeline()) {
+                        graphicsPipelineThreadCount++;
+                    }
+                }
+                if (graphicsPipelineThreadCount > MAX_GRAPHICS_PIPELINE_THREADS_COUNT) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     private ServiceThread createCleanUpThread() {
         final ServiceThread handlerThread = new ServiceThread(TAG,
                 Process.THREAD_PRIORITY_LOWEST, true /*allowIo*/);
@@ -850,6 +914,11 @@
                         mChannelMap.remove(uid);
                     }
                 }
+                synchronized (mCpuHeadroomLock) {
+                    if (mSupportInfo.headroom.isCpuSupported && mUidToLastUserModeJiffies != null) {
+                        mUidToLastUserModeJiffies.remove(uid);
+                    }
+                }
             });
         }
 
@@ -1229,7 +1298,7 @@
             // Only call into AM if the tid is either isolated or invalid
             if (isolatedPids == null) {
                 // To avoid deadlock, do not call into AMS if the call is from system.
-                if (uid == Process.SYSTEM_UID) {
+                if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
                     return tid;
                 }
                 isolatedPids = mAmInternal.getIsolatedProcesses(uid);
@@ -1262,9 +1331,9 @@
     @VisibleForTesting
     final class BinderService extends IHintManager.Stub {
         @Override
-        public IHintSession createHintSessionWithConfig(@NonNull IBinder token,
-                    @SessionTag int tag, SessionCreationConfig creationConfig,
-                    SessionConfig config) {
+        public IHintManager.SessionCreationReturn createHintSessionWithConfig(
+                    @NonNull IBinder token, @SessionTag int tag,
+                    SessionCreationConfig creationConfig, SessionConfig config) {
             if (!isHintSessionSupported()) {
                 throw new UnsupportedOperationException("PowerHintSessions are not supported!");
             }
@@ -1282,8 +1351,24 @@
             final long identity = Binder.clearCallingIdentity();
             final long durationNanos = creationConfig.targetWorkDurationNanos;
 
-            Preconditions.checkArgument(checkGraphicsPipelineValid(creationConfig, callingUid),
-                    "not enough of available graphics pipeline thread.");
+            boolean isGraphicsPipeline = false;
+            boolean isAutoTimed = false;
+            if (creationConfig.modesToEnable != null) {
+                for (int mode : creationConfig.modesToEnable) {
+                    if (mode == SessionMode.GRAPHICS_PIPELINE) {
+                        isGraphicsPipeline = true;
+                    }
+                    if (mode == SessionMode.AUTO_CPU || mode == SessionMode.AUTO_GPU) {
+                        isAutoTimed = true;
+                    }
+                }
+            }
+
+            if (isAutoTimed) {
+                Preconditions.checkArgument(isGraphicsPipeline,
+                        "graphics pipeline mode not enabled for an automatically timed session");
+            }
+
             try {
                 final IntArray nonIsolated = powerhintThreadCleanup() ? new IntArray(tids.length)
                         : null;
@@ -1401,12 +1486,8 @@
                 }
 
                 if (hs != null) {
-                    boolean isGraphicsPipeline = false;
                     if (creationConfig.modesToEnable != null) {
                         for (int sessionMode : creationConfig.modesToEnable) {
-                            if (sessionMode == SessionModes.GRAPHICS_PIPELINE.ordinal()) {
-                                isGraphicsPipeline = true;
-                            }
                             hs.setMode(sessionMode, true);
                         }
                     }
@@ -1425,7 +1506,10 @@
                     }
                 }
 
-                return hs;
+                IHintManager.SessionCreationReturn out = new IHintManager.SessionCreationReturn();
+                out.pipelineThreadLimitExceeded = tooManyPipelineThreads(callingUid);
+                out.session = hs;
+                return out;
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -1484,14 +1568,17 @@
                 throw new UnsupportedOperationException();
             }
             checkCpuHeadroomParams(params);
+            final int uid = Binder.getCallingUid();
+            final int pid = Binder.getCallingPid();
             final CpuHeadroomParams halParams = new CpuHeadroomParams();
-            halParams.tids = new int[]{Binder.getCallingPid()};
+            halParams.tids = new int[]{pid};
             halParams.calculationType = params.calculationType;
             halParams.calculationWindowMillis = params.calculationWindowMillis;
             if (params.usesDeviceHeadroom) {
                 halParams.tids = new int[]{};
             } else if (params.tids != null && params.tids.length > 0) {
-                if (SystemProperties.getBoolean(PROPERTY_CHECK_HEADROOM_TID, true)) {
+                if (UserHandle.getAppId(uid) != Process.SYSTEM_UID && SystemProperties.getBoolean(
+                        PROPERTY_CHECK_HEADROOM_TID, true)) {
                     final int tgid = Process.getThreadGroupLeader(Binder.getCallingPid());
                     for (int tid : params.tids) {
                         if (Process.getThreadGroupLeader(tid) != tgid) {
@@ -1501,6 +1588,10 @@
                         }
                     }
                 }
+                if (cpuHeadroomAffinityCheck() && params.tids.length > 1
+                        && SystemProperties.getBoolean(PROPERTY_CHECK_HEADROOM_AFFINITY, true)) {
+                    checkThreadAffinityForTids(params.tids);
+                }
                 halParams.tids = params.tids;
             }
             if (halParams.calculationWindowMillis
@@ -1510,6 +1601,20 @@
                     if (res != null) return res;
                 }
             }
+            final boolean shouldCheckUserModeCpuTime =
+                    mEnforceCpuHeadroomUserModeCpuTimeCheck
+                            || (UserHandle.getAppId(uid) != Process.SYSTEM_UID
+                            && mContext.checkCallingPermission(
+                            Manifest.permission.DEVICE_POWER)
+                            == PackageManager.PERMISSION_DENIED);
+
+            if (shouldCheckUserModeCpuTime) {
+                synchronized (mCpuHeadroomLock) {
+                    if (!checkPerUidUserModeCpuTimeElapsedLocked(uid)) {
+                        return null;
+                    }
+                }
+            }
             // return from HAL directly
             try {
                 final CpuHeadroomResult result = mPowerHal.getCpuHeadroom(halParams);
@@ -1523,12 +1628,72 @@
                         mCpuHeadroomCache.add(halParams, result);
                     }
                 }
+                if (shouldCheckUserModeCpuTime) {
+                    synchronized (mCpuHeadroomLock) {
+                        mUidToLastUserModeJiffies.put(uid, mLastCpuUserModeJiffies);
+                    }
+                }
                 return result;
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to get CPU headroom from Power HAL", e);
                 return null;
             }
         }
+        private void checkThreadAffinityForTids(int[] tids) {
+            long[] reference = null;
+            for (int tid : tids) {
+                long[] affinity;
+                try {
+                    affinity = Process.getSchedAffinity(tid);
+                } catch (Exception e) {
+                    Slog.e(TAG, "Failed to get affinity " + tid, e);
+                    throw new IllegalStateException("Could not check affinity for tid " + tid);
+                }
+                if (reference == null) {
+                    reference = affinity;
+                } else if (!Arrays.equals(reference, affinity)) {
+                    Slog.d(TAG, "Thread affinity is different: tid "
+                            + tids[0] + "->" + Arrays.toString(reference) + ", tid "
+                            + tid + "->" + Arrays.toString(affinity));
+                    throw new IllegalStateException("Thread affinity is not the same for tids "
+                            + Arrays.toString(tids));
+                }
+            }
+        }
+
+        // check if there has been sufficient user mode cpu time elapsed since last call
+        // from the same uid
+        @GuardedBy("mCpuHeadroomLock")
+        private boolean checkPerUidUserModeCpuTimeElapsedLocked(int uid) {
+            // skip checking proc stat if it's within mCheckHeadroomProcStatMinMillis
+            if (System.currentTimeMillis() - mLastCpuUserModeTimeCheckedMillis
+                    > mCheckHeadroomProcStatMinMillis) {
+                try {
+                    mLastCpuUserModeJiffies = getUserModeJiffies();
+                } catch (Exception e) {
+                    Slog.e(TAG, "Failed to get user mode CPU time", e);
+                    return false;
+                }
+                mLastCpuUserModeTimeCheckedMillis = System.currentTimeMillis();
+            }
+            if (mUidToLastUserModeJiffies.containsKey(uid)) {
+                long uidLastUserModeJiffies = mUidToLastUserModeJiffies.get(uid);
+                if ((mLastCpuUserModeJiffies - uidLastUserModeJiffies) * mJiffyMillis
+                        < mSupportInfo.headroom.cpuMinIntervalMillis) {
+                    Slog.w(TAG, "UID " + uid + " is requesting CPU headroom too soon");
+                    Slog.d(TAG, "UID " + uid + " last request at "
+                            + uidLastUserModeJiffies * mJiffyMillis
+                            + "ms with device currently at "
+                            + mLastCpuUserModeJiffies * mJiffyMillis
+                            + "ms, the interval: "
+                            + (mLastCpuUserModeJiffies - uidLastUserModeJiffies)
+                            * mJiffyMillis + "ms is less than require minimum interval "
+                            + mSupportInfo.headroom.cpuMinIntervalMillis + "ms");
+                    return false;
+                }
+            }
+            return true;
+        }
 
         private void checkCpuHeadroomParams(CpuHeadroomParamsInternal params) {
             boolean calculationTypeMatched = false;
@@ -1705,43 +1870,25 @@
             }
         }
 
-        private boolean checkGraphicsPipelineValid(SessionCreationConfig creationConfig, int uid) {
-            if (creationConfig.modesToEnable == null) {
-                return true;
-            }
-            boolean setGraphicsPipeline = false;
-            for (int modeToEnable : creationConfig.modesToEnable) {
-                if (modeToEnable == SessionModes.GRAPHICS_PIPELINE.ordinal()) {
-                    setGraphicsPipeline = true;
-                }
-            }
-            if (!setGraphicsPipeline) {
-                return true;
-            }
-
-            synchronized (mThreadsUsageObject) {
-                // count used graphics pipeline threads for the calling UID
-                // consider the case that new tids are overlapping with in session tids
-                ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(uid);
-                if (threadsSet == null) {
-                    return true;
-                }
-
-                final int newThreadCount = creationConfig.tids.length;
-                int graphicsPipelineThreadCount = 0;
-                for (ThreadUsageTracker t : threadsSet) {
-                    // count graphics pipeline threads in use
-                    // and exclude overlapping ones
-                    if (t.isGraphicsPipeline()) {
-                        graphicsPipelineThreadCount++;
-                        if (contains(creationConfig.tids, t.getTid())) {
-                            graphicsPipelineThreadCount--;
-                        }
+        private long getUserModeJiffies() throws IOException {
+            String filePath =
+                    mProcStatFilePathOverride == null ? "/proc/stat" : mProcStatFilePathOverride;
+            try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    Matcher matcher = PROC_STAT_CPU_TIME_TOTAL_PATTERN.matcher(line.trim());
+                    if (matcher.find()) {
+                        long userJiffies = Long.parseLong(matcher.group("user"));
+                        long niceJiffies = Long.parseLong(matcher.group("nice"));
+                        Slog.d(TAG,
+                                "user: " + userJiffies + " nice: " + niceJiffies
+                                        + " total " + (userJiffies + niceJiffies));
+                        reader.close();
+                        return userJiffies + niceJiffies;
                     }
                 }
-                return graphicsPipelineThreadCount + newThreadCount
-                        <= MAX_GRAPHICS_PIPELINE_THREADS_COUNT;
             }
+            throw new IllegalStateException("Can't find cpu line in " + filePath);
         }
 
         private void logPerformanceHintSessionAtom(int uid, long sessionId,
@@ -1781,11 +1928,6 @@
         protected Integer mSessionId;
         protected boolean mTrackedBySF;
 
-        enum SessionModes {
-            POWER_EFFICIENCY,
-            GRAPHICS_PIPELINE,
-        };
-
         protected AppHintSession(
                 int uid, int pid, int sessionTag, int[] threadIds, IBinder token,
                 long halSessionPtr, long durationNanos, Integer sessionId) {
@@ -1838,8 +1980,8 @@
                 if (!isHintAllowed()) {
                     return;
                 }
-                Preconditions.checkArgument(targetDurationNanos > 0, "Expected"
-                        + " the target duration to be greater than 0.");
+                Preconditions.checkArgument(targetDurationNanos >= 0, "Expected"
+                        + " the target duration to be greater than or equal to 0.");
                 mNativeWrapper.halUpdateTargetWorkDuration(mHalSessionPtr, targetDurationNanos);
                 mTargetDurationNanos = targetDurationNanos;
             }
@@ -2002,6 +2144,11 @@
 
         public void setThreads(@NonNull int[] tids) {
             setThreadsInternal(tids, true);
+            if (tooManyPipelineThreads(Binder.getCallingUid())) {
+                // This is technically a success but we are going to throw a fit anyway
+                throw new ServiceSpecificException(5,
+                                    "Not enough available graphics pipeline threads.");
+            }
         }
 
         private void setThreadsInternal(int[] tids, boolean checkTid) {
@@ -2009,32 +2156,7 @@
                 throw new IllegalArgumentException("Thread id list can't be empty.");
             }
 
-
             final int callingUid = Binder.getCallingUid();
-            if (mGraphicsPipeline) {
-                synchronized (mThreadsUsageObject) {
-                    // replace original tids with new tids
-                    ArraySet<ThreadUsageTracker> threadsSet = mThreadsUsageMap.get(callingUid);
-                    int graphicsPipelineThreadCount = 0;
-                    if (threadsSet != null) {
-                        // We count the graphics pipeline threads that are
-                        // *not* in this session, since those in this session
-                        // will be replaced. Then if the count plus the new tids
-                        // is over max available graphics pipeline threads we raise
-                        // an exception.
-                        for (ThreadUsageTracker t : threadsSet) {
-                            if (t.isGraphicsPipeline() && !contains(mThreadIds, t.getTid())) {
-                                graphicsPipelineThreadCount++;
-                            }
-                        }
-                        if (graphicsPipelineThreadCount + tids.length
-                                > MAX_GRAPHICS_PIPELINE_THREADS_COUNT) {
-                            throw new IllegalArgumentException(
-                                    "Not enough available graphics pipeline threads.");
-                        }
-                    }
-                }
-            }
 
             synchronized (this) {
                 if (mHalSessionPtr == 0) {
@@ -2168,15 +2290,15 @@
                 }
                 Preconditions.checkArgument(mode >= 0, "the mode Id value should be"
                         + " greater than zero.");
-                if (mode == SessionModes.POWER_EFFICIENCY.ordinal()) {
+                if (mode == SessionMode.POWER_EFFICIENCY) {
                     mPowerEfficient = enabled;
-                } else if (mode == SessionModes.GRAPHICS_PIPELINE.ordinal()) {
+                } else if (mode == SessionMode.GRAPHICS_PIPELINE) {
                     mGraphicsPipeline = enabled;
                 }
                 mNativeWrapper.halSetMode(mHalSessionPtr, mode, enabled);
             }
             if (enabled) {
-                if (mode == SessionModes.POWER_EFFICIENCY.ordinal()) {
+                if (mode == SessionMode.POWER_EFFICIENCY) {
                     if (!mHasBeenPowerEfficient) {
                         mHasBeenPowerEfficient = true;
                         synchronized (mSessionSnapshotMapLock) {
@@ -2195,7 +2317,7 @@
                             sessionSnapshot.logPowerEfficientSession();
                         }
                     }
-                } else if (mode == SessionModes.GRAPHICS_PIPELINE.ordinal()) {
+                } else if (mode == SessionMode.GRAPHICS_PIPELINE) {
                     if (!mHasBeenGraphicsPipeline) {
                         mHasBeenGraphicsPipeline = true;
                         synchronized (mSessionSnapshotMapLock) {
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index e80a86d..4fd026a 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -285,14 +285,20 @@
     }
 
     private void updateCacheFile(String cacheFilename, byte[] data) {
+        AtomicFile atomicCachedFile = null;
+        FileOutputStream fos = null;
         try {
-            final AtomicFile atomicCachedFile =
+            atomicCachedFile =
                     new AtomicFile(new File(mDataStoragePath, cacheFilename));
-            final FileOutputStream fos = atomicCachedFile.startWrite();
+            fos = atomicCachedFile.startWrite();
             fos.write(data);
             atomicCachedFile.finishWrite(fos);
         } catch (IOException e) {
             Slog.e(TAG, "Failed to write current data to cached file", e);
+            if (fos != null) {
+                atomicCachedFile.failWrite(fos);
+            }
+            return;
         }
     }
 
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 1bed48a..2e6be5b 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1251,12 +1251,12 @@
                 // should document in PackageInstaller.SessionParams#setEnableRollback
                 // After enabling and committing any rollback, observe packages and
                 // prepare to rollback if packages crashes too frequently.
-                mPackageWatchdog.startExplicitHealthCheck(mPackageHealthObserver,
-                        rollback.getPackageNames(), mRollbackLifetimeDurationInMillis);
+                mPackageWatchdog.startExplicitHealthCheck(rollback.getPackageNames(),
+                        mRollbackLifetimeDurationInMillis, mPackageHealthObserver);
             }
         } else {
-            mPackageWatchdog.startExplicitHealthCheck(mPackageHealthObserver,
-                    rollback.getPackageNames(), mRollbackLifetimeDurationInMillis);
+            mPackageWatchdog.startExplicitHealthCheck(rollback.getPackageNames(),
+                    mRollbackLifetimeDurationInMillis, mPackageHealthObserver);
         }
         runExpiration();
     }
diff --git a/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java b/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java
index 083b1fd..f303a58 100644
--- a/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java
+++ b/services/core/java/com/android/server/security/intrusiondetection/NetworkLogSource.java
@@ -129,7 +129,8 @@
                                     timestamp);
                     dnsEvent.setId(mId);
                     incrementEventID();
-                    mDataAggregator.addSingleData(new IntrusionDetectionEvent(dnsEvent));
+                    mDataAggregator.addSingleData(
+                            IntrusionDetectionEvent.createForDnsEvent(dnsEvent));
                 }
 
                 @Override
@@ -141,7 +142,8 @@
                             new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid), timestamp);
                     connectEvent.setId(mId);
                     incrementEventID();
-                    mDataAggregator.addSingleData(new IntrusionDetectionEvent(connectEvent));
+                    mDataAggregator.addSingleData(
+                            IntrusionDetectionEvent.createForConnectEvent(connectEvent));
                 }
             };
 }
diff --git a/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java b/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
index 5611905..142094c 100644
--- a/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
+++ b/services/core/java/com/android/server/security/intrusiondetection/SecurityLogSource.java
@@ -89,7 +89,7 @@
             List<IntrusionDetectionEvent> intrusionDetectionEvents =
                     events.stream()
                             .filter(event -> event != null)
-                            .map(event -> new IntrusionDetectionEvent(event))
+                            .map(event -> IntrusionDetectionEvent.createForSecurityEvent(event))
                             .collect(Collectors.toList());
             mDataAggregator.addBatchData(intrusionDetectionEvents);
         }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index f8877ad..c18918f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -2175,6 +2175,19 @@
         }
     }
 
+    /**
+     *  Called when the notification should be unbundled.
+     * @param key the notification key
+     */
+    @Override
+    public void unbundleNotification(@Nullable String key) {
+        enforceStatusBarService();
+        enforceValidCallingUser();
+        Binder.withCleanCallingIdentity(() -> {
+            mNotificationDelegate.unbundleNotification(key);
+        });
+    }
+
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index dad3a78..bb163ef 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -369,10 +369,9 @@
                 tagName = parser.getName();
                 if (TAG_QUOTA.equals(tagName)) {
                     CacheQuotaHint request = getRequestFromXml(parser);
-                    if (request == null) {
-                        continue;
+                    if (request != null) {
+                        quotas.add(request);
                     }
-                    quotas.add(request);
                 }
             }
             eventType = parser.next();
diff --git a/services/core/java/com/android/server/updates/Android.bp b/services/core/java/com/android/server/updates/Android.bp
deleted file mode 100644
index 10beebb..0000000
--- a/services/core/java/com/android/server/updates/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-aconfig_declarations {
-    name: "updates_flags",
-    package: "com.android.server.updates",
-    container: "system",
-    srcs: ["*.aconfig"],
-}
-
-java_aconfig_library {
-    name: "updates_flags_lib",
-    aconfig_declarations: "updates_flags",
-}
diff --git a/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java b/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java
deleted file mode 100644
index af4025e..0000000
--- a/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.updates;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.FileUtils;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.util.Slog;
-
-import libcore.io.Streams;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-
-public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInstallReceiver {
-
-    private static final String TAG = "CTLogInstallReceiver";
-    private static final String LOGDIR_PREFIX = "logs-";
-
-    public CertificateTransparencyLogInstallReceiver() {
-        super("/data/misc/keychain/ct/", "ct_logs", "metadata/", "version");
-    }
-
-    @Override
-    protected void install(InputStream inputStream, int version) throws IOException {
-        if (!Flags.certificateTransparencyInstaller()) {
-            return;
-        }
-        // To support atomically replacing the old configuration directory with the new there's a
-        // bunch of steps. We create a new directory with the logs and then do an atomic update of
-        // the current symlink to point to the new directory.
-        // 1. Ensure that the update dir exists and is readable
-        updateDir.mkdir();
-        if (!updateDir.isDirectory()) {
-            throw new IOException("Unable to make directory " + updateDir.getCanonicalPath());
-        }
-        if (!updateDir.setReadable(true, false)) {
-            throw new IOException("Unable to set permissions on " + updateDir.getCanonicalPath());
-        }
-        File currentSymlink = new File(updateDir, "current");
-        File newVersion = new File(updateDir, LOGDIR_PREFIX + String.valueOf(version));
-        // 2. Handle the corner case where the new directory already exists.
-        if (newVersion.exists()) {
-            // If the symlink has already been updated then the update died between steps 7 and 8
-            // and so we cannot delete the directory since its in use. Instead just bump the version
-            // and return.
-            if (newVersion.getCanonicalPath().equals(currentSymlink.getCanonicalPath())) {
-                writeUpdate(
-                        updateDir,
-                        updateVersion,
-                        new ByteArrayInputStream(Long.toString(version).getBytes()));
-                deleteOldLogDirectories();
-                return;
-            } else {
-                FileUtils.deleteContentsAndDir(newVersion);
-            }
-        }
-        try {
-            // 3. Create /data/misc/keychain/ct/<new_version>/ .
-            newVersion.mkdir();
-            if (!newVersion.isDirectory()) {
-                throw new IOException("Unable to make directory " + newVersion.getCanonicalPath());
-            }
-            if (!newVersion.setReadable(true, false)) {
-                throw new IOException(
-                        "Failed to set " + newVersion.getCanonicalPath() + " readable");
-            }
-
-            // 4. Validate the log list json and move the file in <new_version>/ .
-            installLogList(newVersion, inputStream);
-
-            // 5. Create the temp symlink. We'll rename this to the target symlink to get an atomic
-            // update.
-            File tempSymlink = new File(updateDir, "new_symlink");
-            try {
-                Os.symlink(newVersion.getCanonicalPath(), tempSymlink.getCanonicalPath());
-            } catch (ErrnoException e) {
-                throw new IOException("Failed to create symlink", e);
-            }
-
-            // 6. Update the symlink target, this is the actual update step.
-            tempSymlink.renameTo(currentSymlink.getAbsoluteFile());
-        } catch (IOException | RuntimeException e) {
-            FileUtils.deleteContentsAndDir(newVersion);
-            throw e;
-        }
-        Slog.i(TAG, "CT log directory updated to " + newVersion.getAbsolutePath());
-        // 7. Update the current version information
-        writeUpdate(
-                updateDir,
-                updateVersion,
-                new ByteArrayInputStream(Long.toString(version).getBytes()));
-        // 8. Cleanup
-        deleteOldLogDirectories();
-    }
-
-    @Override
-    protected void postInstall(Context context, Intent intent) {
-        if (!Flags.certificateTransparencyInstaller()) {
-            return;
-        }
-    }
-
-    private void installLogList(File directory, InputStream inputStream) throws IOException {
-        try {
-            byte[] content = Streams.readFullyNoClose(inputStream);
-            if (new JSONObject(new String(content, StandardCharsets.UTF_8)).length() == 0) {
-                throw new IOException("Log list data not valid");
-            }
-
-            File file = new File(directory, "log_list.json");
-            try (FileOutputStream outputStream = new FileOutputStream(file)) {
-                outputStream.write(content);
-            }
-            if (!file.setReadable(true, false)) {
-                throw new IOException("Failed to set permissions on " + file.getCanonicalPath());
-            }
-        } catch (JSONException e) {
-            throw new IOException("Malformed json in log list", e);
-        }
-    }
-
-    private void deleteOldLogDirectories() throws IOException {
-        if (!updateDir.exists()) {
-            return;
-        }
-        File currentTarget = new File(updateDir, "current").getCanonicalFile();
-        FileFilter filter =
-                new FileFilter() {
-                    @Override
-                    public boolean accept(File file) {
-                        return !currentTarget.equals(file)
-                                && file.getName().startsWith(LOGDIR_PREFIX);
-                    }
-                };
-        for (File f : updateDir.listFiles(filter)) {
-            FileUtils.deleteContentsAndDir(f);
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/updates/flags.aconfig b/services/core/java/com/android/server/updates/flags.aconfig
deleted file mode 100644
index 476cb37..0000000
--- a/services/core/java/com/android/server/updates/flags.aconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-package: "com.android.server.updates"
-container: "system"
-
-flag {
-    name: "certificate_transparency_installer"
-    is_exported: true
-    namespace: "network_security"
-    description: "Enable certificate transparency installer for log list data"
-    bug: "319829948"
-}
diff --git a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
index 19eba5f..90c2216 100644
--- a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
+++ b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
@@ -51,8 +51,11 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.server.wm.utils.InsetUtils;
+import com.android.window.flags.Flags;
 
 import java.io.PrintWriter;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
 
 /**
  * Base class for a Snapshot controller
@@ -148,43 +151,60 @@
     protected abstract Rect getLetterboxInsets(ActivityRecord topActivity);
 
     /**
-     * This is different than {@link #recordSnapshotInner(TYPE)} because it doesn't store
-     * the snapshot to the cache and returns the TaskSnapshot immediately.
-     *
-     * This is only used for testing so the snapshot content can be verified.
+     * This is different than {@link #recordSnapshotInner(TYPE, boolean, Consumer)}  because it
+     * doesn't store the snapshot to the cache and returns the TaskSnapshot immediately.
      */
     @VisibleForTesting
-    TaskSnapshot captureSnapshot(TYPE source) {
-        final TaskSnapshot snapshot;
+    SnapshotSupplier captureSnapshot(TYPE source, boolean allowAppTheme) {
+        final SnapshotSupplier supplier = new SnapshotSupplier();
         switch (getSnapshotMode(source)) {
-            case SNAPSHOT_MODE_NONE:
-                return null;
             case SNAPSHOT_MODE_APP_THEME:
-                snapshot = drawAppThemeSnapshot(source);
+                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "drawAppThemeSnapshot");
+                if (Flags.excludeDrawingAppThemeSnapshotFromLock()) {
+                    if (allowAppTheme) {
+                        supplier.setSupplier(drawAppThemeSnapshot(source));
+                    }
+                } else {
+                    final Supplier<TaskSnapshot> original = drawAppThemeSnapshot(source);
+                    final TaskSnapshot snapshot = original != null ? original.get() : null;
+                    supplier.setSnapshot(snapshot);
+                }
+                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
                 break;
             case SNAPSHOT_MODE_REAL:
-                snapshot = snapshot(source);
+                supplier.setSnapshot(snapshot(source));
                 break;
             default:
-                snapshot = null;
                 break;
         }
-        return snapshot;
+        return supplier;
     }
 
-    final TaskSnapshot recordSnapshotInner(TYPE source) {
+    /**
+     * @param allowAppTheme If true, allows to draw app theme snapshot when it's not allowed to take
+     *                      a real screenshot, but create a fake representation of the app.
+     * @param inLockConsumer Extra task to do in WM lock when first get the snapshot object.
+     */
+    final SnapshotSupplier recordSnapshotInner(TYPE source, boolean allowAppTheme,
+            @Nullable Consumer<TaskSnapshot> inLockConsumer) {
         if (shouldDisableSnapshots()) {
             return null;
         }
-        final TaskSnapshot snapshot = captureSnapshot(source);
-        if (snapshot == null) {
-            return null;
-        }
-        mCache.putSnapshot(source, snapshot);
-        return snapshot;
+        final SnapshotSupplier supplier = captureSnapshot(source, allowAppTheme);
+        supplier.setConsumer(t -> {
+            synchronized (mService.mGlobalLock) {
+                if (!source.isAttached()) {
+                    return;
+                }
+                mCache.putSnapshot(source, t);
+                if (inLockConsumer != null) {
+                    inLockConsumer.accept(t);
+                }
+            }
+        });
+        return supplier;
     }
 
-    @VisibleForTesting
     int getSnapshotMode(TYPE source) {
         final int type = source.getActivityType();
         if (type == ACTIVITY_TYPE_RECENTS || type == ACTIVITY_TYPE_DREAM) {
@@ -400,7 +420,7 @@
      * If we are not allowed to take a real screenshot, this attempts to represent the app as best
      * as possible by using the theme's window background.
      */
-    private TaskSnapshot drawAppThemeSnapshot(TYPE source) {
+    private Supplier<TaskSnapshot> drawAppThemeSnapshot(TYPE source) {
         final ActivityRecord topActivity = getTopActivity(source);
         if (topActivity == null) {
             return null;
@@ -432,26 +452,46 @@
         decorPainter.setInsets(systemBarInsets);
         decorPainter.drawDecors(c /* statusBarExcludeFrame */, null /* alreadyDrawFrame */);
         node.end(c);
-        final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
-        if (hwBitmap == null) {
-            return null;
-        }
+
         final Rect contentInsets = new Rect(systemBarInsets);
         final Rect letterboxInsets = getLetterboxInsets(topActivity);
         InsetUtils.addInsets(contentInsets, letterboxInsets);
-        // Note, the app theme snapshot is never translucent because we enforce a non-translucent
-        // color above
-        final TaskSnapshot taskSnapshot = new TaskSnapshot(
-                System.currentTimeMillis() /* id */,
-                SystemClock.elapsedRealtimeNanos() /* captureTime */,
-                topActivity.mActivityComponent, hwBitmap.getHardwareBuffer(),
-                hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation,
-                mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight),
-                contentInsets, letterboxInsets, false /* isLowResolution */,
-                false /* isRealSnapshot */, source.getWindowingMode(),
-                attrs.insetsFlags.appearance, false /* isTranslucent */, false /* hasImeSurface */,
-                topActivity.getConfiguration().uiMode /* uiMode */);
-        return validateSnapshot(taskSnapshot);
+
+        final TaskSnapshot.Builder builder = new TaskSnapshot.Builder();
+        builder.setIsRealSnapshot(false);
+        builder.setId(System.currentTimeMillis());
+        builder.setContentInsets(contentInsets);
+        builder.setLetterboxInsets(letterboxInsets);
+
+        builder.setTopActivityComponent(topActivity.mActivityComponent);
+        // Note, the app theme snapshot is never translucent because we enforce a
+        // non-translucent color above.
+        builder.setIsTranslucent(false);
+        builder.setWindowingMode(source.getWindowingMode());
+        builder.setAppearance(attrs.insetsFlags.appearance);
+        builder.setUiMode(topActivity.getConfiguration().uiMode);
+
+        builder.setRotation(mainWindow.getWindowConfiguration().getRotation());
+        builder.setOrientation(mainWindow.getConfiguration().orientation);
+        builder.setTaskSize(new Point(taskWidth, taskHeight));
+        builder.setCaptureTime(SystemClock.elapsedRealtimeNanos());
+
+        return () -> {
+            try {
+                Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "drawAppThemeSnapshot_acquire");
+                // Do not hold WM lock when calling to render thread.
+                final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width,
+                        height);
+                if (hwBitmap == null) {
+                    return null;
+                }
+                builder.setSnapshot(hwBitmap.getHardwareBuffer());
+                builder.setColorSpace(hwBitmap.getColorSpace());
+                return validateSnapshot(builder.build());
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+            }
+        };
     }
 
     static Rect getSystemBarInsets(Rect frame, InsetsState state) {
@@ -482,4 +522,45 @@
         pw.println(prefix + "mSnapshotEnabled=" + mSnapshotEnabled);
         mCache.dump(pw, prefix);
     }
+
+    static class SnapshotSupplier implements Supplier<TaskSnapshot> {
+
+        private TaskSnapshot mSnapshot;
+        private boolean mHasSet;
+        private Consumer<TaskSnapshot> mConsumer;
+        private Supplier<TaskSnapshot> mSupplier;
+
+        /** Callback when the snapshot is get for the first time. */
+        void setConsumer(@NonNull Consumer<TaskSnapshot> consumer) {
+            mConsumer = consumer;
+        }
+
+        void setSupplier(@NonNull Supplier<TaskSnapshot> createSupplier) {
+            mSupplier = createSupplier;
+        }
+
+        void setSnapshot(TaskSnapshot snapshot) {
+            mSnapshot = snapshot;
+        }
+
+        void handleSnapshot() {
+            if (mHasSet) {
+                return;
+            }
+            mHasSet = true;
+            if (mSnapshot == null) {
+                mSnapshot = mSupplier != null ? mSupplier.get() : null;
+            }
+            if (mConsumer != null && mSnapshot != null) {
+                mConsumer.accept(mSnapshot);
+            }
+        }
+
+        @Override
+        @Nullable
+        public TaskSnapshot get() {
+            handleSnapshot();
+            return mSnapshot;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 83b273c..b71256d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3227,7 +3227,7 @@
             return false;
         }
         // If the user preference respects aspect ratio, then it becomes non-resizable.
-        return mAppCompatController.getAppCompatOverrides().getAppCompatAspectRatioOverrides()
+        return mAppCompatController.getAppCompatAspectRatioOverrides()
                 .userPreferenceCompatibleWithNonResizability();
     }
 
@@ -3898,11 +3898,18 @@
         final TaskFragment taskFragment = getTaskFragment();
         if (next != null && taskFragment != null && taskFragment.isEmbedded()) {
             final TaskFragment organized = taskFragment.getOrganizedTaskFragment();
-            final TaskFragment adjacent =
-                    organized != null ? organized.getAdjacentTaskFragment() : null;
-            if (adjacent != null && next.isDescendantOf(adjacent)
-                    && organized.topRunningActivity() == null) {
-                delayRemoval = organized.isDelayLastActivityRemoval();
+            if (Flags.allowMultipleAdjacentTaskFragments()) {
+                delayRemoval = organized != null
+                        && organized.topRunningActivity() == null
+                        && organized.isDelayLastActivityRemoval()
+                        && organized.forOtherAdjacentTaskFragments(next::isDescendantOf);
+            } else {
+                final TaskFragment adjacent =
+                        organized != null ? organized.getAdjacentTaskFragment() : null;
+                if (adjacent != null && next.isDescendantOf(adjacent)
+                        && organized.topRunningActivity() == null) {
+                    delayRemoval = organized.isDelayLastActivityRemoval();
+                }
             }
         }
 
@@ -4880,15 +4887,25 @@
      *  @see #canShowWhenLocked(ActivityRecord)
      */
     boolean canShowWhenLocked() {
-        final TaskFragment taskFragment = getTaskFragment();
-        if (taskFragment != null && taskFragment.getAdjacentTaskFragment() != null
-                && taskFragment.isEmbedded()) {
-            final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
-            final ActivityRecord r = adjacentTaskFragment.getTopNonFinishingActivity();
-            return canShowWhenLocked(this) && canShowWhenLocked(r);
-        } else {
-            return canShowWhenLocked(this);
+        if (!canShowWhenLocked(this)) {
+            return false;
         }
+        final TaskFragment taskFragment = getTaskFragment();
+        if (taskFragment == null || !taskFragment.hasAdjacentTaskFragment()
+                || !taskFragment.isEmbedded()) {
+            // No embedded adjacent that need to be checked.
+            return true;
+        }
+
+        // Make sure the embedded adjacent can also be shown.
+        if (!Flags.allowMultipleAdjacentTaskFragments()) {
+            final ActivityRecord adjacentActivity = taskFragment.getAdjacentTaskFragment()
+                    .getTopNonFinishingActivity();
+            return canShowWhenLocked(adjacentActivity);
+        }
+        final boolean hasAdjacentNotAllowToShow = taskFragment.forOtherAdjacentTaskFragments(
+                adjacentTF -> !canShowWhenLocked(adjacentTF.getTopNonFinishingActivity()));
+        return !hasAdjacentNotAllowToShow;
     }
 
     /**
@@ -8528,8 +8545,7 @@
         // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
         // are already calculated in resolveFixedOrientationConfiguration.
         // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
-        if (Flags.immersiveAppRepositioning()
-                && !mAppCompatController.getAppCompatAspectRatioPolicy()
+        if (!mAppCompatController.getAppCompatAspectRatioPolicy()
                     .isLetterboxedForFixedOrientationAndAspectRatio()
                 && !mAppCompatController.getAppCompatAspectRatioOverrides()
                     .hasFullscreenOverride()) {
@@ -8551,18 +8567,6 @@
                 computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
             }
         }
-        // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
-        // are already calculated in resolveFixedOrientationConfiguration, or if in size compat
-        // mode, it should already be calculated in resolveSizeCompatModeConfiguration.
-        // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
-        if (!Flags.immersiveAppRepositioning()
-                && !mAppCompatController.getAppCompatAspectRatioPolicy()
-                    .isLetterboxedForFixedOrientationAndAspectRatio()
-                && !scmPolicy.isInSizeCompatModeForBounds()
-                && !mAppCompatController.getAppCompatAspectRatioOverrides()
-                    .hasFullscreenOverride()) {
-            resolveAspectRatioRestriction(newParentConfiguration);
-        }
 
         if (isFixedOrientationLetterboxAllowed
                 || scmPolicy.hasAppCompatDisplayInsetsWithoutInheritance()
@@ -8819,9 +8823,6 @@
     }
 
     boolean isImmersiveMode(@NonNull Rect parentBounds) {
-        if (!Flags.immersiveAppRepositioning()) {
-            return false;
-        }
         if (!mResolveConfigHint.mUseOverrideInsetsForConfig
                 && mWmService.mFlags.mInsetsDecoupledConfiguration) {
             return false;
@@ -10355,7 +10356,9 @@
         }
         if (!isVisibleRequested()) {
             // TODO(b/294925498): Remove this finishing check once we have accurate ready tracking.
-            if (task != null && task.getPausingActivity() == this) {
+            if (task != null && task.getPausingActivity() == this
+                    // Display is asleep, so nothing will be visible anyways.
+                    && !mDisplayContent.isSleeping()) {
                 // Visibility of starting activities isn't calculated until pause-complete, so if
                 // this is not paused yet, don't consider it ready.
                 return false;
diff --git a/services/core/java/com/android/server/wm/ActivityRefresher.java b/services/core/java/com/android/server/wm/ActivityRefresher.java
index ed8b689..597f75a 100644
--- a/services/core/java/com/android/server/wm/ActivityRefresher.java
+++ b/services/core/java/com/android/server/wm/ActivityRefresher.java
@@ -115,8 +115,8 @@
     private boolean shouldRefreshActivity(@NonNull ActivityRecord activity,
             @NonNull Configuration newConfig, @NonNull Configuration lastReportedConfig) {
         return mWmService.mAppCompatConfiguration.isCameraCompatRefreshEnabled()
-                && activity.mAppCompatController.getAppCompatOverrides()
-                    .getAppCompatCameraOverrides().shouldRefreshActivityForCameraCompat()
+                && activity.mAppCompatController.getAppCompatCameraOverrides()
+                    .shouldRefreshActivityForCameraCompat()
                 && ArrayUtils.find(mEvaluators.toArray(), evaluator ->
                 ((Evaluator) evaluator)
                         .shouldRefreshActivity(activity, newConfig, lastReportedConfig)) != null;
diff --git a/services/core/java/com/android/server/wm/ActivitySnapshotController.java b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
index 9aaa0e1..cfd3248 100644
--- a/services/core/java/com/android/server/wm/ActivitySnapshotController.java
+++ b/services/core/java/com/android/server/wm/ActivitySnapshotController.java
@@ -38,6 +38,7 @@
 import java.io.File;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.function.Supplier;
 
 /**
  * When an app token becomes invisible, we take a snapshot (bitmap) and put it into our cache.
@@ -355,7 +356,9 @@
         final int[] mixedCode = new int[size];
         if (size == 1) {
             final ActivityRecord singleActivity = activity.get(0);
-            final TaskSnapshot snapshot = recordSnapshotInner(singleActivity);
+            final Supplier<TaskSnapshot> supplier = recordSnapshotInner(singleActivity,
+                    false /* allowAppTheme */, null /* inLockConsumer */);
+            final TaskSnapshot snapshot = supplier != null ? supplier.get() : null;
             if (snapshot != null) {
                 mixedCode[0] = getSystemHashCode(singleActivity);
                 addUserSavedFile(singleActivity.mUserId, snapshot, mixedCode);
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1a9d211..6709e3a 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -25,6 +25,9 @@
 import static android.app.admin.DevicePolicyManager.EXTRA_RESTRICTION;
 import static android.app.admin.DevicePolicyManager.POLICY_SUSPEND_PACKAGES;
 import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.CATEGORY_SECONDARY_HOME;
 import static android.content.Intent.EXTRA_INTENT;
 import static android.content.Intent.EXTRA_PACKAGE_NAME;
 import static android.content.Intent.EXTRA_TASK_ID;
@@ -40,6 +43,7 @@
 import android.app.KeyguardManager;
 import android.app.TaskInfo;
 import android.app.admin.DevicePolicyManagerInternal;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentSender;
 import android.content.Intent;
@@ -67,6 +71,7 @@
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult;
+import com.android.window.flags.Flags;
 
 /**
  * A class that contains activity intercepting logic for {@link ActivityStarter#execute()}
@@ -119,6 +124,11 @@
      */
     TaskDisplayArea mPresumableLaunchDisplayArea;
 
+    /**
+     * Whether the component is specified originally in the given Intent.
+     */
+    boolean mComponentSpecified;
+
     ActivityStartInterceptor(
             ActivityTaskManagerService service, ActivityTaskSupervisor supervisor) {
         this(service, supervisor, service.mContext);
@@ -185,6 +195,14 @@
         return TaskFragment.fromTaskFragmentToken(taskFragToken, mService);
     }
 
+    // TODO: consolidate this method with the one below since this is used for test only.
+    boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
+            Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
+            ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea) {
+        return intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment, callingPid,
+                callingUid, activityOptions, presumableLaunchDisplayArea, false);
+    }
+
     /**
      * Intercept the launch intent based on various signals. If an interception happened the
      * internal variables get assigned and need to be read explicitly by the caller.
@@ -193,7 +211,8 @@
      */
     boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
             Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
-            ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea) {
+            ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea,
+            boolean componentSpecified) {
         mUserManager = UserManager.get(mServiceContext);
 
         mIntent = intent;
@@ -206,6 +225,7 @@
         mInTaskFragment = inTaskFragment;
         mActivityOptions = activityOptions;
         mPresumableLaunchDisplayArea = presumableLaunchDisplayArea;
+        mComponentSpecified = componentSpecified;
 
         if (interceptQuietProfileIfNeeded()) {
             // If work profile is turned off, skip the work challenge since the profile can only
@@ -230,7 +250,8 @@
         }
         if (interceptHomeIfNeeded()) {
             // Replace primary home intents directed at displays that do not support primary home
-            // but support secondary home with the relevant secondary home activity.
+            // but support secondary home with the relevant secondary home activity. Or the home
+            // intent is not in the correct format.
             return true;
         }
 
@@ -479,9 +500,78 @@
         if (mPresumableLaunchDisplayArea == null || mService.mRootWindowContainer == null) {
             return false;
         }
-        if (!ActivityRecord.isHomeIntent(mIntent)) {
-            return false;
+
+        boolean intercepted = false;
+        if (Flags.normalizeHomeIntent()) {
+            if (!ACTION_MAIN.equals(mIntent.getAction()) || (!mIntent.hasCategory(CATEGORY_HOME)
+                    && !mIntent.hasCategory(CATEGORY_SECONDARY_HOME))) {
+                // not a home intent
+                return false;
+            }
+
+            if (mComponentSpecified) {
+                final ComponentName homeComponent = mIntent.getComponent();
+                final Intent homeIntent = mService.getHomeIntent();
+                final ActivityInfo aInfo = mService.mRootWindowContainer.resolveHomeActivity(
+                        mUserId, homeIntent);
+                if (!aInfo.getComponentName().equals(homeComponent)) {
+                    // Do nothing if the intent is not for the default home component.
+                    return false;
+                }
+            }
+
+            if (!ActivityRecord.isHomeIntent(mIntent) || mComponentSpecified) {
+                // This is not a standard home intent, make it so if possible.
+                normalizeHomeIntent();
+                intercepted = true;
+            }
+        } else {
+            if (!ActivityRecord.isHomeIntent(mIntent)) {
+                return false;
+            }
         }
+
+        intercepted |= replaceToSecondaryHomeIntentIfNeeded();
+        if (intercepted) {
+            mCallingPid = mRealCallingPid;
+            mCallingUid = mRealCallingUid;
+            mResolvedType = null;
+
+            mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
+                    mRealCallingUid, mRealCallingPid);
+            mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/
+                    null);
+        }
+        return intercepted;
+    }
+
+    private void normalizeHomeIntent() {
+        Slog.w(TAG, "The home Intent is not correctly formatted");
+        if (mIntent.getCategories().size() > 1) {
+            Slog.d(TAG, "Purge home intent categories");
+            boolean isSecondaryHome = false;
+            final Object[] categories = mIntent.getCategories().toArray();
+            for (int i = categories.length - 1; i >= 0; i--) {
+                final String category = (String) categories[i];
+                if (CATEGORY_SECONDARY_HOME.equals(category)) {
+                    isSecondaryHome = true;
+                }
+                mIntent.removeCategory(category);
+            }
+            mIntent.addCategory(isSecondaryHome ? CATEGORY_SECONDARY_HOME : CATEGORY_HOME);
+        }
+        if (mIntent.getType() != null || mIntent.getData() != null) {
+            Slog.d(TAG, "Purge home intent data/type");
+            mIntent.setType(null);
+        }
+        if (mComponentSpecified) {
+            Slog.d(TAG, "Purge home intent component, " + mIntent.getComponent());
+            mIntent.setComponent(null);
+        }
+        mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+    }
+
+    private boolean replaceToSecondaryHomeIntentIfNeeded() {
         if (!mIntent.hasCategory(Intent.CATEGORY_HOME)) {
             // Already a secondary home intent, leave it alone.
             return false;
@@ -506,13 +596,6 @@
         // and should not be moved to the caller's task. Also, activities cannot change their type,
         // e.g. a standard activity cannot become a home activity.
         mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
-        mCallingPid = mRealCallingPid;
-        mCallingUid = mRealCallingUid;
-        mResolvedType = null;
-
-        mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
-                mRealCallingUid, mRealCallingPid);
-        mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/ null);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index acb9384..0ab2ffe 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1341,7 +1341,8 @@
                 callingPackage,
                 callingFeatureId);
         if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
-                callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
+                callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea,
+                request.componentSpecified)) {
             // activity start was intercepted, e.g. because the target user is currently in quiet
             // mode (turn off work) or the target application is suspended
             intent = mInterceptor.mIntent;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5eee8ec..2971e8e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -314,6 +314,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.Supplier;
 
 /**
  * System service for managing activities and their containers (task, displays,... ).
@@ -437,10 +438,13 @@
 
     /** It is set from keyguard-going-away to set-keyguard-shown. */
     static final int DEMOTE_TOP_REASON_DURING_UNLOCKING = 1;
+    /** It is set when notification shade occludes the foreground app. */
+    static final int DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE = 1 << 1;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
             DEMOTE_TOP_REASON_DURING_UNLOCKING,
+            DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE,
     })
     @interface DemoteTopReason {}
 
@@ -4038,6 +4042,7 @@
         mAmInternal.enforceCallingPermission(READ_FRAME_BUFFER, "takeTaskSnapshot()");
         final long ident = Binder.clearCallingIdentity();
         try {
+            final Supplier<TaskSnapshot> supplier;
             synchronized (mGlobalLock) {
                 final Task task = mRootWindowContainer.anyTaskForId(taskId,
                         MATCH_ATTACHED_TASK_OR_RECENT_TASKS);
@@ -4050,11 +4055,13 @@
                 // be retrieved by recents. While if updateCache is false, the real snapshot will
                 // always be taken and the snapshot won't be put into SnapshotPersister.
                 if (updateCache) {
-                    return mWindowManager.mTaskSnapshotController.recordSnapshot(task);
+                    supplier = mWindowManager.mTaskSnapshotController
+                            .getRecordSnapshotSupplier(task);
                 } else {
                     return mWindowManager.mTaskSnapshotController.snapshot(task);
                 }
             }
+            return supplier != null ? supplier.get() : null;
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -5243,6 +5250,12 @@
                 : mRootWindowContainer.getTopResumedActivity();
         mTopApp = top != null ? top.app : null;
         if (mTopApp == mPreviousProcess) mPreviousProcess = null;
+
+        final int demoteReasons = mDemoteTopAppReasons;
+        if ((demoteReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) != 0) {
+            Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancel-demote-top-for-ns-switch");
+            mDemoteTopAppReasons = demoteReasons & ~DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
+        }
     }
 
     /**
@@ -6403,6 +6416,7 @@
         @Override
         public boolean shuttingDown(boolean booted, int timeout) {
             mShuttingDown = true;
+            mWindowManager.mSnapshotController.mTaskSnapshotController.prepareShutdown();
             synchronized (mGlobalLock) {
                 mRootWindowContainer.prepareForShutdown();
                 updateEventDispatchingLocked(booted);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 0aff1de..bf57f56 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -77,6 +77,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
 import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_TASK_MSG;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
 import static com.android.server.wm.ClientLifecycleManager.shouldDispatchLaunchActivityItemIndependently;
 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
@@ -2525,7 +2526,7 @@
     void scheduleUpdatePictureInPictureModeIfNeeded(Task task, Rect targetRootTaskBounds) {
         task.forAllActivities(r -> {
             if (!r.attachedToProcess()) return;
-            mPipModeChangedActivities.add(r);
+            if (!isPip2ExperimentEnabled()) mPipModeChangedActivities.add(r);
             // If we are scheduling pip change, then remove this activity from multi-window
             // change list as the processing of pip change will make sure multi-window changed
             // message is processed in the right order relative to pip changed.
@@ -2534,7 +2535,7 @@
 
         mPipModeChangedTargetRootTaskBounds = targetRootTaskBounds;
 
-        if (!mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
+        if (!isPip2ExperimentEnabled() && !mHandler.hasMessages(REPORT_PIP_MODE_CHANGED_MSG)) {
             mHandler.sendEmptyMessage(REPORT_PIP_MODE_CHANGED_MSG);
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
index e8eae4f..6a0de98 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN;
 import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE;
@@ -36,6 +37,8 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 
+import com.android.window.flags.Flags;
+
 /**
  * Encapsulate app compat policy logic related to aspect ratio.
  */
@@ -239,7 +242,14 @@
                 || AppCompatUtils.isInVrUiMode(mActivityRecord.getConfiguration())
                 // TODO(b/232898850): Always respect aspect ratio requests.
                 // Don't set aspect ratio for activity in ActivityEmbedding split.
-                || (organizedTf != null && !organizedTf.fillsParent())) {
+                || (organizedTf != null && !organizedTf.fillsParent())
+                // Don't set aspect ratio for resizeable activities in freeform.
+                // {@link ActivityRecord#shouldCreateAppCompatDisplayInsets()} will be false for
+                // both activities that are naturally resizeable and activities that have been
+                // forced resizeable.
+                || (Flags.ignoreAspectRatioRestrictionsForResizeableFreeformActivities()
+                    && task.getWindowingMode() == WINDOWING_MODE_FREEFORM
+                    && !mActivityRecord.shouldCreateAppCompatDisplayInsets())) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
index 9547e5cc..6074608 100644
--- a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
@@ -39,7 +39,8 @@
     @VisibleForTesting
     final CameraStateMonitor mCameraStateMonitor;
     @Nullable
-    private final ActivityRefresher mActivityRefresher;
+    @VisibleForTesting
+    final ActivityRefresher mActivityRefresher;
     @Nullable
     final DisplayRotationCompatPolicy mDisplayRotationCompatPolicy;
     @Nullable
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index 330283f..4433d64 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -123,11 +123,6 @@
     }
 
     @NonNull
-    AppCompatOverrides getAppCompatOverrides() {
-        return mAppCompatOverrides;
-    }
-
-    @NonNull
     AppCompatOrientationOverrides getAppCompatOrientationOverrides() {
         return mAppCompatOverrides.getAppCompatOrientationOverrides();
     }
diff --git a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
index 4e390df..e929fb4 100644
--- a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
@@ -281,7 +281,6 @@
                         mActivityRecord.mWmService.mTransactionFactory,
                         reachabilityPolicy, letterboxOverrides,
                         this::getLetterboxParentSurface);
-                mLetterbox.attachInput(w);
                 mActivityRecord.mAppCompatController.getAppCompatReachabilityPolicy()
                         .setLetterboxInnerBoundsSupplier(mLetterbox::getInnerFrame);
             }
@@ -335,7 +334,7 @@
             }
             start(winHint);
             if (isRunning() && mLetterbox.needsApplySurfaceChanges()) {
-                mLetterbox.applySurfaceChanges(t, inputT);
+                mLetterbox.applySurfaceChanges(t, inputT, winHint);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
index caff96b..4fac81b 100644
--- a/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatReachabilityOverrides.java
@@ -35,8 +35,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 
-import com.android.window.flags.Flags;
-
 /**
  * Encapsulate overrides and configurations about app compat reachability.
  */
@@ -157,33 +155,27 @@
     }
 
     /**
-     * @return {@value true} if the vertical reachability should be allowed in case of
+     * @return {@code true} if the vertical reachability should be allowed in case of
      * thin letterboxing.
      */
     boolean allowVerticalReachabilityForThinLetterbox() {
-        if (!Flags.disableThinLetterboxingPolicy()) {
-            return true;
-        }
         // When the flag is enabled we allow vertical reachability only if the
         // app is not thin letterboxed vertically.
         return !isVerticalThinLetterboxed();
     }
 
     /**
-     * @return {@value true} if the horizontal reachability should be enabled in case of
+     * @return {@code true} if the horizontal reachability should be enabled in case of
      * thin letterboxing.
      */
     boolean allowHorizontalReachabilityForThinLetterbox() {
-        if (!Flags.disableThinLetterboxingPolicy()) {
-            return true;
-        }
         // When the flag is enabled we allow horizontal reachability only if the
         // app is not thin pillarboxed.
         return !isHorizontalThinLetterboxed();
     }
 
     /**
-     * @return {@value true} if the resulting app is letterboxed in a way defined as thin.
+     * @return {@code true} if the resulting app is letterboxed in a way defined as thin.
      */
     boolean isVerticalThinLetterboxed() {
         final int thinHeight = mAppCompatConfiguration.getThinLetterboxHeightPx();
@@ -200,7 +192,7 @@
     }
 
     /**
-     * @return {@value true} if the resulting app is pillarboxed in a way defined as thin.
+     * @return {@code true} if the resulting app is pillarboxed in a way defined as thin.
      */
     boolean isHorizontalThinLetterboxed() {
         final int thinWidth = mAppCompatConfiguration.getThinLetterboxWidthPx();
diff --git a/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java b/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java
index f3b043b..d278dc3 100644
--- a/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java
@@ -28,8 +28,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 
-import com.android.window.flags.Flags;
-
 import java.io.PrintWriter;
 import java.util.function.DoubleSupplier;
 
@@ -202,9 +200,7 @@
         // saved here before resolved bounds are overridden below.
         final AppCompatAspectRatioPolicy aspectRatioPolicy = mActivityRecord.mAppCompatController
                 .getAppCompatAspectRatioPolicy();
-        final boolean useResolvedBounds = Flags.immersiveAppRepositioning()
-                ? aspectRatioPolicy.isAspectRatioApplied()
-                : aspectRatioPolicy.isLetterboxedForFixedOrientationAndAspectRatio();
+        final boolean useResolvedBounds = aspectRatioPolicy.isAspectRatioApplied();
         final Rect containerBounds = useResolvedBounds
                 ? new Rect(resolvedBounds)
                 : newParentConfiguration.windowConfiguration.getBounds();
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index 0369a0f..9f88bc9 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -164,15 +164,13 @@
 
         appCompatTaskInfo.setIsFromLetterboxDoubleTap(reachabilityOverrides.isFromDoubleTap());
 
+        appCompatTaskInfo.topActivityAppBounds.set(getAppBounds(top));
         final boolean isTopActivityLetterboxed = top.areBoundsLetterboxed();
         appCompatTaskInfo.setTopActivityLetterboxed(isTopActivityLetterboxed);
         if (isTopActivityLetterboxed) {
             final Rect bounds = top.getBounds();
-            final Rect appBounds = getAppBounds(top);
             appCompatTaskInfo.topActivityLetterboxWidth = bounds.width();
             appCompatTaskInfo.topActivityLetterboxHeight = bounds.height();
-            appCompatTaskInfo.topActivityLetterboxAppWidth = appBounds.width();
-            appCompatTaskInfo.topActivityLetterboxAppHeight = appBounds.height();
             // TODO(b/379824541) Remove duplicate information.
             appCompatTaskInfo.topActivityLetterboxBounds = bounds;
             // We need to consider if letterboxed or pillarboxed.
@@ -281,8 +279,7 @@
         info.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
         info.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET;
         info.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET;
-        info.topActivityLetterboxAppHeight = TaskInfo.PROPERTY_VALUE_UNSET;
-        info.topActivityLetterboxAppWidth = TaskInfo.PROPERTY_VALUE_UNSET;
+        info.topActivityAppBounds.setEmpty();
         info.topActivityLetterboxBounds = null;
         info.cameraCompatTaskInfo.freeformCameraCompatMode =
                 CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_UNSPECIFIED;
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index dd1af0a..6b6f011 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -29,9 +29,6 @@
 import android.view.WindowManager;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-
-import com.android.internal.R;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -687,11 +684,12 @@
 
     @Override
     public Animation getFadeInAnimation() {
+        final Animation anim = super.getFadeInAnimation();
         if (mHasScreenRotationAnimation) {
             // Use a shorter animation so it is easier to align with screen rotation animation.
-            return AnimationUtils.loadAnimation(mContext, R.anim.screen_rotate_0_enter);
+            anim.setDuration(getScaledDuration(SHORT_DURATION_MS));
         }
-        return super.getFadeInAnimation();
+        return anim;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 1a7c6b7..fc0df64 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -111,9 +111,7 @@
     }
 
     void onEmbeddedWindowGestureTransferred(@NonNull WindowState host) {
-        if (Flags.disallowAppProgressEmbeddedWindow()) {
-            mNavigationMonitor.onEmbeddedWindowGestureTransferred(host);
-        }
+        mNavigationMonitor.onEmbeddedWindowGestureTransferred(host);
     }
 
     /**
@@ -215,7 +213,7 @@
                 infoBuilder.setFocusedTaskId(currentTask.mTaskId);
             }
             boolean transferGestureToEmbedded = false;
-            if (Flags.disallowAppProgressEmbeddedWindow() && embeddedWindows != null) {
+            if (embeddedWindows != null) {
                 for (int i = embeddedWindows.size() - 1; i >= 0; --i) {
                     if (embeddedWindows.get(i).mGestureToEmbedded) {
                         transferGestureToEmbedded = true;
@@ -997,11 +995,9 @@
     /**
      * Handle the pending animation when the running transition finished, all the visibility change
      * has applied so ready to start pending predictive back animation.
-     * @param targets The final animation targets derived in transition.
      * @param finishedTransition The finished transition target.
     */
-    void onTransitionFinish(ArrayList<Transition.ChangeInfo> targets,
-            @NonNull Transition finishedTransition) {
+    void onTransitionFinish(@NonNull Transition finishedTransition) {
         if (isMonitoringPrepareTransition(finishedTransition)) {
             if (mAnimationHandler.mPrepareCloseTransition == null) {
                 clearBackAnimations(true /* cancel */);
@@ -1049,14 +1045,6 @@
             return;
         }
 
-        // Ensure the final animation targets which hidden by transition could be visible.
-        for (int i = 0; i < targets.size(); i++) {
-            final WindowContainer wc = targets.get(i).mContainer;
-            if (wc.mSurfaceControl != null) {
-                wc.prepareSurfaces();
-            }
-        }
-
         // The pending builder could be cleared due to prepareSurfaces
         // => updateNonSystemOverlayWindowsVisibilityIfNeeded
         // => setForceHideNonSystemOverlayWindowIfNeeded
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 852a0ac..f9a06e2 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -616,7 +616,6 @@
     }
 
     static class BalVerdict {
-
         static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked");
         static final BalVerdict ALLOW_BY_DEFAULT =
                 new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default");
@@ -640,6 +639,9 @@
         }
 
         public BalVerdict withProcessInfo(String msg, WindowProcessController process) {
+            if (this == BLOCK || this == ALLOW_BY_DEFAULT || this == ALLOW_PRIVILEGED) {
+                return this;
+            }
             mProcessInfo = msg + " (uid=" + process.mUid + ",pid=" + process.getPid() + ")";
             return this;
         }
@@ -653,6 +655,10 @@
         }
 
         void setOnlyCreatorAllows(boolean onlyCreatorAllows) {
+            if (this == BLOCK) {
+                // do not modify BLOCK constant
+                return;
+            }
             mOnlyCreatorAllows = onlyCreatorAllows;
         }
 
@@ -662,6 +668,10 @@
 
         @VisibleForTesting
         BalVerdict setBasedOnRealCaller() {
+            if (this == BLOCK) {
+                // do not modify BLOCK constant
+                return this;
+            }
             mBasedOnRealCaller = true;
             return this;
         }
@@ -669,22 +679,29 @@
         public String toString() {
             StringBuilder builder = new StringBuilder();
             builder.append(balCodeToString(mCode));
-            if (DEBUG_ACTIVITY_STARTS) {
-                builder.append(" (");
-                if (mBackground) {
-                    builder.append("Background ");
+            if (this != BLOCK) {
+                if (mOnlyCreatorAllows) {
+                    builder.append(" [onlyCaller]");
+                } else if (mBasedOnRealCaller) {
+                    builder.append(" [realCaller]");
                 }
-                builder.append("Activity start ");
-                if (mCode == BAL_BLOCK) {
-                    builder.append("denied");
-                } else {
-                    builder.append("allowed: ").append(mMessage);
+                if (DEBUG_ACTIVITY_STARTS) {
+                    builder.append(" (");
+                    if (mBackground) {
+                        builder.append("Background ");
+                    }
+                    builder.append("Activity start ");
+                    if (mCode == BAL_BLOCK) {
+                        builder.append("denied");
+                    } else {
+                        builder.append("allowed: ").append(mMessage);
+                    }
+                    if (mProcessInfo != null) {
+                        builder.append(" ");
+                        builder.append(mProcessInfo);
+                    }
+                    builder.append(")");
                 }
-                if (mProcessInfo != null) {
-                    builder.append(" ");
-                    builder.append(mProcessInfo);
-                }
-                builder.append(")");
             }
             return builder.toString();
         }
@@ -785,9 +802,8 @@
                         .setBasedOnRealCaller();
         state.setResultForRealCaller(resultForRealCaller);
 
-        if (state.isPendingIntent()) {
-            resultForCaller.setOnlyCreatorAllows(
-                    resultForCaller.allows() && resultForRealCaller.blocks());
+        if (state.isPendingIntent() && resultForCaller.allows() && resultForRealCaller.blocks()) {
+            resultForCaller.setOnlyCreatorAllows(true);
         }
 
         // Handle cases with explicit opt-in
@@ -1091,11 +1107,6 @@
         // don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
         if (mService.hasSystemAlertWindowPermission(state.mCallingUid, state.mCallingPid,
                 state.mCallingPackage)) {
-            Slog.w(
-                    TAG,
-                    "Background activity start for "
-                            + state.mCallingPackage
-                            + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
             return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
                     /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
         }
@@ -1167,18 +1178,9 @@
         }
 
         // don't abort if the realCallingUid has SYSTEM_ALERT_WINDOW permission
-        Slog.i(TAG, "hasSystemAlertWindowPermission(" + state.mRealCallingUid + ", "
-                + state.mRealCallingPid + ", " + state.mRealCallingPackage + ") "
-                + balStartModeToString(
-                state.mCheckedOptions.getPendingIntentBackgroundActivityStartMode()));
         if (allowAlways
                 && mService.hasSystemAlertWindowPermission(state.mRealCallingUid,
                 state.mRealCallingPid, state.mRealCallingPackage)) {
-            Slog.w(
-                    TAG,
-                    "Background activity start for "
-                            + state.mRealCallingPackage
-                            + " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
             return new BalVerdict(BAL_ALLOW_SAW_PERMISSION,
                     /*background*/ true, "SYSTEM_ALERT_WINDOW permission is granted");
         }
diff --git a/services/core/java/com/android/server/wm/CameraStateMonitor.java b/services/core/java/com/android/server/wm/CameraStateMonitor.java
index 3aa3558..0027992 100644
--- a/services/core/java/com/android/server/wm/CameraStateMonitor.java
+++ b/services/core/java/com/android/server/wm/CameraStateMonitor.java
@@ -110,8 +110,10 @@
     }
 
     void startListeningToCameraState() {
-        mCameraManager.registerAvailabilityCallback(
-                mWmService.mContext.getMainExecutor(), mAvailabilityCallback);
+        if (mCameraManager != null) {
+            mCameraManager.registerAvailabilityCallback(
+                    mWmService.mContext.getMainExecutor(), mAvailabilityCallback);
+        }
         mIsRunning = true;
     }
 
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index 8eccffd..a4e58ef 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -368,6 +368,15 @@
             return;
         }
 
+        final SurfaceControl sourceSurface = mRecordedWindowContainer.getSurfaceControl();
+        if (sourceSurface == null || !sourceSurface.isValid()) {
+            ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
+                    "Content Recording: Unable to start recording for display %d since the "
+                            + "surface is null or have been released.",
+                    mDisplayContent.getDisplayId());
+            return;
+        }
+
         final int contentToRecord = mContentRecordingSession.getContentToRecord();
 
         // TODO(b/297514518) Do not start capture if the app is in PIP, the bounds are inaccurate.
@@ -395,8 +404,7 @@
                 mDisplayContent.getDisplayId(), mDisplayContent.getDisplayInfo().state);
 
         // Create a mirrored hierarchy for the SurfaceControl of the DisplayArea to capture.
-        mRecordedSurface = SurfaceControl.mirrorSurface(
-                mRecordedWindowContainer.getSurfaceControl());
+        mRecordedSurface = SurfaceControl.mirrorSurface(sourceSurface);
         SurfaceControl.Transaction transaction =
                 mDisplayContent.mWmService.mTransactionFactory.get()
                         // Set the mMirroredSurface's parent to the root SurfaceControl for this
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f808661..5c3fbdf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -440,7 +440,6 @@
     private boolean mSandboxDisplayApis = true;
 
     /** Whether {@link #setIgnoreOrientationRequest} is called to override the default policy. */
-    @VisibleForTesting
     boolean mHasSetIgnoreOrientationRequest;
 
     /**
@@ -2908,6 +2907,18 @@
                 && !mDisplayRotation.isRotatingSeamlessly()) {
             clearFixedRotationLaunchingApp();
         }
+        // If there won't be a transition to notify the launch is done, then it should be ready to
+        // update with display orientation. E.g. a translucent activity enters pip from a task which
+        // contains another opaque activity.
+        if (mFixedRotationLaunchingApp != null && mFixedRotationLaunchingApp.isVisible()
+                && !mTransitionController.isCollecting()
+                && !mAtmService.mBackNavigationController.isMonitoringFinishTransition()) {
+            final Transition finishTransition = mTransitionController.mFinishingTransition;
+            if (finishTransition == null || !finishTransition.mParticipants.contains(
+                    mFixedRotationLaunchingApp)) {
+                continueUpdateOrientationForDiffOrienLaunchingApp();
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f0ba822..4ae1008 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -376,6 +376,9 @@
 
         if (settings.mIgnoreOrientationRequest != null) {
             dc.setIgnoreOrientationRequest(settings.mIgnoreOrientationRequest);
+        } else if (dc.mHasSetIgnoreOrientationRequest) {
+            // Null entry is default behavior, i.e. do not ignore.
+            dc.setIgnoreOrientationRequest(false);
         }
 
         dc.getDisplayRotation().resetAllowAllRotations();
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 258a87e..3c60d82 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -289,7 +289,8 @@
                 transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha);
                 transaction.show(surfaceControl);
                 displayContent.reparentToOverlay(transaction, surfaceControl);
-                mDragState.updateDragSurfaceLocked(true, touchX, touchY);
+                mDragState.updateDragSurfaceLocked(true /* keepHandling */,
+                        displayContent.getDisplayId(), touchX, touchY);
                 if (SHOW_LIGHT_TRANSACTIONS) {
                     Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
                 }
@@ -483,10 +484,11 @@
      * Handles motion events.
      * @param keepHandling Whether if the drag operation is continuing or this is the last motion
      *          event.
+     * @param displayId id of the display the X,Y coordinate is n.
      * @param newX X coordinate value in dp in the screen coordinate
      * @param newY Y coordinate value in dp in the screen coordinate
      */
-    void handleMotionEvent(boolean keepHandling, float newX, float newY) {
+    void handleMotionEvent(boolean keepHandling, int displayId, float newX, float newY) {
         synchronized (mService.mGlobalLock) {
             if (!dragDropActiveLocked()) {
                 // The drag has ended but the clean-up message has not been processed by
@@ -495,7 +497,7 @@
                 return;
             }
 
-            mDragState.updateDragSurfaceLocked(keepHandling, newX, newY);
+            mDragState.updateDragSurfaceLocked(keepHandling, displayId, newX, newY);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DragInputEventReceiver.java b/services/core/java/com/android/server/wm/DragInputEventReceiver.java
index 5372d8b..8f4548f 100644
--- a/services/core/java/com/android/server/wm/DragInputEventReceiver.java
+++ b/services/core/java/com/android/server/wm/DragInputEventReceiver.java
@@ -22,13 +22,13 @@
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.os.Looper;
 import android.util.Slog;
 import android.view.InputChannel;
-import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.InputEventReceiver;
 import android.view.MotionEvent;
@@ -63,6 +63,7 @@
                 return;
             }
             final MotionEvent motionEvent = (MotionEvent) event;
+            final int displayId = motionEvent.getDisplayId();
             final float newX = motionEvent.getRawX();
             final float newY = motionEvent.getRawY();
             final boolean isStylusButtonDown =
@@ -102,7 +103,8 @@
                     return;
             }
 
-            mDragDropController.handleMotionEvent(!mMuteInput /* keepHandling */, newX, newY);
+            mDragDropController.handleMotionEvent(!mMuteInput /* keepHandling */, displayId, newX,
+                    newY);
             handled = true;
         } catch (Exception e) {
             Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 1c4e487..3a0e41a 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -113,8 +113,8 @@
     boolean mRelinquishDragSurfaceToDropTarget;
     float mAnimatedScale = 1.0f;
     float mOriginalAlpha;
-    float mOriginalX, mOriginalY;
-    float mCurrentX, mCurrentY;
+    float mOriginalDisplayX, mOriginalDisplayY;
+    float mCurrentDisplayX, mCurrentDisplayY;
     float mThumbOffsetX, mThumbOffsetY;
     InputInterceptor mInputInterceptor;
     ArrayList<WindowState> mNotifiedWindows;
@@ -230,22 +230,22 @@
         if (mDragInProgress) {
             if (DEBUG_DRAG) Slog.d(TAG_WM, "Broadcasting DRAG_ENDED");
             for (WindowState ws : mNotifiedWindows) {
-                float x = 0;
-                float y = 0;
+                float inWindowX = 0;
+                float inWindowY = 0;
                 SurfaceControl dragSurface = null;
                 if (!mDragResult && (ws.mSession.mPid == mPid)) {
                     // Report unconsumed drop location back to the app that started the drag.
-                    x = ws.translateToWindowX(mCurrentX);
-                    y = ws.translateToWindowY(mCurrentY);
+                    inWindowX = ws.translateToWindowX(mCurrentDisplayX);
+                    inWindowY = ws.translateToWindowY(mCurrentDisplayY);
                     if (relinquishDragSurfaceToDragSource()) {
                         // If requested (and allowed), report the drag surface back to the app
                         // starting the drag to handle the return animation
                         dragSurface = mSurfaceControl;
                     }
                 }
-                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, x, y,
-                        mThumbOffsetX, mThumbOffsetY, mFlags, null, null, null, dragSurface, null,
-                        mDragResult);
+                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, inWindowX,
+                        inWindowY, mThumbOffsetX, mThumbOffsetY, mFlags, null, null, null,
+                        dragSurface, null, mDragResult);
                 try {
                     if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DRAG_ENDED to " + ws);
                     ws.mClient.dispatchDragEvent(event);
@@ -297,70 +297,71 @@
     }
 
     /**
-     * Creates the drop event for this drag gesture.  If `touchedWin` is null, then the drop event
-     * will be created for dispatching to the unhandled drag and the drag surface will be provided
-     * as a part of the dispatched event.
+     * Creates the drop event for dispatching to the unhandled drag.
+     * TODO(b/384841906): Update `inWindowX` and `inWindowY` to be display-coordinate.
      */
-    private DragEvent createDropEvent(float x, float y, @Nullable WindowState touchedWin,
-            boolean includePrivateInfo) {
-        if (touchedWin != null) {
-            final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
-            final DragAndDropPermissionsHandler dragAndDropPermissions;
-            if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
-                    && mData != null) {
-                dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
-                        mData,
-                        mUid,
-                        touchedWin.getOwningPackage(),
-                        mFlags & DRAG_FLAGS_URI_PERMISSIONS,
-                        mSourceUserId,
-                        targetUserId);
-            } else {
-                dragAndDropPermissions = null;
-            }
-            if (mSourceUserId != targetUserId) {
-                if (mData != null) {
-                    mData.fixUris(mSourceUserId);
-                }
-            }
-            final boolean targetInterceptsGlobalDrag = targetInterceptsGlobalDrag(touchedWin);
-            return obtainDragEvent(DragEvent.ACTION_DROP, x, y, mDataDescription, mData,
-                    /* includeDragSurface= */ targetInterceptsGlobalDrag,
-                    /* includeDragFlags= */ targetInterceptsGlobalDrag,
-                    dragAndDropPermissions);
+    private DragEvent createUnhandledDropEvent(float inWindowX, float inWindowY) {
+        return obtainDragEvent(DragEvent.ACTION_DROP, inWindowX, inWindowY, mDataDescription, mData,
+                /* includeDragSurface= */ true,
+                /* includeDragFlags= */ true, null /* dragAndDropPermissions */);
+    }
+
+    /**
+     * Creates the drop event for this drag gesture.
+     */
+    private DragEvent createDropEvent(float inWindowX, float inWindowY, WindowState touchedWin) {
+        final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
+        final DragAndDropPermissionsHandler dragAndDropPermissions;
+        if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
+                && mData != null) {
+            dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock, mData,
+                    mUid, touchedWin.getOwningPackage(), mFlags & DRAG_FLAGS_URI_PERMISSIONS,
+                    mSourceUserId, targetUserId);
         } else {
-            return obtainDragEvent(DragEvent.ACTION_DROP, x, y, mDataDescription, mData,
-                    /* includeDragSurface= */ includePrivateInfo,
-                    /* includeDragFlags= */ includePrivateInfo,
-                    null /* dragAndDropPermissions */);
+            dragAndDropPermissions = null;
         }
+        if (mSourceUserId != targetUserId) {
+            if (mData != null) {
+                mData.fixUris(mSourceUserId);
+            }
+        }
+        final boolean targetInterceptsGlobalDrag = targetInterceptsGlobalDrag(touchedWin);
+        return obtainDragEvent(DragEvent.ACTION_DROP, inWindowX, inWindowY, mDataDescription, mData,
+                /* includeDragSurface= */ targetInterceptsGlobalDrag,
+                /* includeDragFlags= */ targetInterceptsGlobalDrag, dragAndDropPermissions);
     }
 
     /**
      * Notify the drop target and tells it about the data. If the drop event is not sent to the
      * target, invokes {@code endDragLocked} after the unhandled drag listener gets a chance to
      * handle the drop.
+     * @param inWindowX if `token` refers to a dragEvent-accepting window, `inWindowX` will be
+     *                  inside the window, else values might be invalid (0, 0).
+     * @param inWindowY if `token` refers to a dragEvent-accepting window, `inWindowY` will be
+     *                  inside the window, else values might be invalid (0, 0).
      */
-    boolean reportDropWindowLock(IBinder token, float x, float y) {
+    boolean reportDropWindowLock(IBinder token, float inWindowX, float inWindowY) {
         if (mAnimator != null) {
             return false;
         }
         try {
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "DragDropController#DROP");
-            return reportDropWindowLockInner(token, x, y);
+            return reportDropWindowLockInner(token, inWindowX, inWindowY);
         } finally {
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         }
     }
 
-    private boolean reportDropWindowLockInner(IBinder token, float x, float y) {
+    private boolean reportDropWindowLockInner(IBinder token, float inWindowX, float inWindowY) {
         if (mAnimator != null) {
             return false;
         }
 
         final WindowState touchedWin = mService.mInputToWindowMap.get(token);
-        final DragEvent unhandledDropEvent = createDropEvent(x, y, null /* touchedWin */,
-                true /* includePrivateInfo */);
+        // TODO(b/384841906): The x, y here when sent to a window and unhandled, will still be
+        //  relative to the window it was originally sent to. Need to update this to actually be
+        //  display-coordinate.
+        final DragEvent unhandledDropEvent = createUnhandledDropEvent(inWindowX, inWindowY);
         if (!isWindowNotified(touchedWin)) {
             // Delegate to the unhandled drag listener as a first pass
             if (mDragDropController.notifyUnhandledDrop(unhandledDropEvent, "unhandled-drop")) {
@@ -381,7 +382,7 @@
         if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DROP to " + touchedWin);
 
         final IBinder clientToken = touchedWin.mClient.asBinder();
-        final DragEvent event = createDropEvent(x, y, touchedWin, false /* includePrivateInfo */);
+        final DragEvent event = createDropEvent(inWindowX, inWindowY, touchedWin);
         try {
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "DragDropController#dispatchDrop");
             touchedWin.mClient.dispatchDragEvent(event);
@@ -486,8 +487,8 @@
      */
     void broadcastDragStartedLocked(final float touchX, final float touchY) {
         Trace.instant(TRACE_TAG_WINDOW_MANAGER, "DragDropController#DRAG_STARTED");
-        mOriginalX = mCurrentX = touchX;
-        mOriginalY = mCurrentY = touchY;
+        mOriginalDisplayX = mCurrentDisplayX = touchX;
+        mOriginalDisplayY = mCurrentDisplayY = touchY;
 
         // Cache a base-class instance of the clip metadata so that parceling
         // works correctly in calling out to the apps.
@@ -636,7 +637,7 @@
             if (isWindowNotified(newWin)) {
                 return;
             }
-            sendDragStartedLocked(newWin, mCurrentX, mCurrentY,
+            sendDragStartedLocked(newWin, mCurrentDisplayX, mCurrentDisplayY,
                     containsApplicationExtras(mDataDescription));
         }
     }
@@ -685,12 +686,21 @@
         mAnimator = createCancelAnimationLocked();
     }
 
-    void updateDragSurfaceLocked(boolean keepHandling, float x, float y) {
+    /**
+     * Updates the position of the drag surface.
+     *
+     * @param keepHandling whether to keep handling the drag.
+     * @param displayId the display ID of the drag surface.
+     * @param displayX the x-coordinate of the drag surface in the display's coordinate frame.
+     * @param displayY the y-coordinate of the drag surface in the display's coordinate frame.
+     */
+    void updateDragSurfaceLocked(boolean keepHandling, int displayId, float displayX,
+            float displayY) {
         if (mAnimator != null) {
             return;
         }
-        mCurrentX = x;
-        mCurrentY = y;
+        mCurrentDisplayX = displayX;
+        mCurrentDisplayY = displayY;
 
         if (!keepHandling) {
             return;
@@ -700,9 +710,10 @@
         if (SHOW_LIGHT_TRANSACTIONS) {
             Slog.i(TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
         }
-        mTransaction.setPosition(mSurfaceControl, x - mThumbOffsetX, y - mThumbOffsetY).apply();
-        ProtoLog.i(WM_SHOW_TRANSACTIONS, "DRAG %s: pos=(%d,%d)", mSurfaceControl,
-                (int) (x - mThumbOffsetX), (int) (y - mThumbOffsetY));
+        mTransaction.setPosition(mSurfaceControl, displayX - mThumbOffsetX,
+                displayY - mThumbOffsetY).apply();
+        ProtoLog.i(WM_SHOW_TRANSACTIONS, "DRAG %s: displayId=%d, pos=(%d,%d)", mSurfaceControl,
+                displayId, (int) (displayX - mThumbOffsetX), (int) (displayY - mThumbOffsetY));
     }
 
     /**
@@ -713,6 +724,12 @@
         return mDragInProgress;
     }
 
+    /**
+     * `x` and `y` here varies between local window coordinate, relative coordinate to another
+     * window and local display coordinate, all depending on the `action`. Please take a look
+     * at the callers to determine the type.
+     * TODO(b/384845022): Properly document the events sent based on the event type.
+     */
     private DragEvent obtainDragEvent(int action, float x, float y, ClipDescription description,
             ClipData data, boolean includeDragSurface, boolean includeDragFlags,
             IDragAndDropPermissions dragAndDropPermissions) {
@@ -728,34 +745,34 @@
         final long duration;
         if (mCallingTaskIdToHide != -1) {
             animator = ValueAnimator.ofPropertyValuesHolder(
-                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentX, mCurrentX),
-                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentY, mCurrentY),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentDisplayX,
+                            mCurrentDisplayX),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentDisplayY,
+                            mCurrentDisplayY),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                             mAnimatedScale),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0f));
             duration = MIN_ANIMATION_DURATION_MS;
         } else {
             animator = ValueAnimator.ofPropertyValuesHolder(
-                    PropertyValuesHolder.ofFloat(
-                            ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX,
-                            mOriginalX - mThumbOffsetX),
-                    PropertyValuesHolder.ofFloat(
-                            ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY,
-                            mOriginalY - mThumbOffsetY),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X,
+                            mCurrentDisplayX - mThumbOffsetX, mOriginalDisplayX - mThumbOffsetX),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y,
+                            mCurrentDisplayY - mThumbOffsetY, mOriginalDisplayY - mThumbOffsetY),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                             mAnimatedScale),
-                    PropertyValuesHolder.ofFloat(
-                            ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, mOriginalAlpha / 2));
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha,
+                            mOriginalAlpha / 2));
 
-            final float translateX = mOriginalX - mCurrentX;
-            final float translateY = mOriginalY - mCurrentY;
+            final float translateX = mOriginalDisplayX - mCurrentDisplayX;
+            final float translateY = mOriginalDisplayY - mCurrentDisplayY;
             // Adjust the duration to the travel distance.
             final double travelDistance = Math.sqrt(
                     translateX * translateX + translateY * translateY);
-            final double displayDiagonal =
-                    Math.sqrt(mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
-            duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal
-                    * (MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
+            final double displayDiagonal = Math.sqrt(
+                    mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
+            duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal * (
+                    MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
         }
 
         final AnimationListener listener = new AnimationListener();
@@ -771,18 +788,20 @@
     private ValueAnimator createCancelAnimationLocked() {
         final ValueAnimator animator;
         if (mCallingTaskIdToHide != -1) {
-             animator = ValueAnimator.ofPropertyValuesHolder(
-                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentX, mCurrentX),
-                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentY, mCurrentY),
+            animator = ValueAnimator.ofPropertyValuesHolder(
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentDisplayX,
+                            mCurrentDisplayX),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentDisplayY,
+                            mCurrentDisplayY),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                             mAnimatedScale),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0f));
         } else {
             animator = ValueAnimator.ofPropertyValuesHolder(
-                    PropertyValuesHolder.ofFloat(
-                            ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX, mCurrentX),
-                    PropertyValuesHolder.ofFloat(
-                            ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY, mCurrentY),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X,
+                            mCurrentDisplayX - mThumbOffsetX, mCurrentDisplayX),
+                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y,
+                            mCurrentDisplayY - mThumbOffsetY, mCurrentDisplayY),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale, 0),
                     PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0));
         }
diff --git a/services/core/java/com/android/server/wm/FadeAnimationController.java b/services/core/java/com/android/server/wm/FadeAnimationController.java
index 7af67e6..c60d367 100644
--- a/services/core/java/com/android/server/wm/FadeAnimationController.java
+++ b/services/core/java/com/android/server/wm/FadeAnimationController.java
@@ -20,41 +20,51 @@
 import static com.android.server.wm.WindowAnimationSpecProto.ANIMATION;
 
 import android.annotation.NonNull;
-import android.content.Context;
 import android.util.proto.ProtoOutputStream;
 import android.view.SurfaceControl;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Transformation;
 
-import com.android.internal.R;
-
 import java.io.PrintWriter;
 
 /**
  * An animation controller to fade-in/out for a window token.
  */
 public class FadeAnimationController {
+    static final int SHORT_DURATION_MS = 200;
+    static final int MEDIUM_DURATION_MS = 350;
+
     protected final DisplayContent mDisplayContent;
-    protected final Context mContext;
 
     public FadeAnimationController(DisplayContent displayContent) {
         mDisplayContent = displayContent;
-        mContext = displayContent.mWmService.mContext;
     }
 
     /**
      * @return a fade-in Animation.
      */
     public Animation getFadeInAnimation() {
-        return AnimationUtils.loadAnimation(mContext, R.anim.fade_in);
+        final AlphaAnimation anim = new AlphaAnimation(0f, 1f);
+        anim.setDuration(getScaledDuration(MEDIUM_DURATION_MS));
+        anim.setInterpolator(new DecelerateInterpolator());
+        return anim;
     }
 
     /**
      * @return a fade-out Animation.
      */
     public Animation getFadeOutAnimation() {
-        return AnimationUtils.loadAnimation(mContext, R.anim.fade_out);
+        final AlphaAnimation anim = new AlphaAnimation(1f, 0f);
+        anim.setDuration(getScaledDuration(SHORT_DURATION_MS));
+        anim.setInterpolator(new AccelerateInterpolator());
+        return anim;
+    }
+
+    long getScaledDuration(int durationMs) {
+        return (long) (durationMs * mDisplayContent.mWmService.getWindowAnimationScaleLocked());
     }
 
     /** Run the fade in/out animation for a window token. */
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index cf145f9..ce85184 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -374,12 +374,6 @@
     void notifyControlChanged(InsetsControlTarget target, InsetsSourceProvider provider) {
         addToPendingControlMaps(target, provider);
         notifyPendingInsetsControlChanged();
-
-        if (android.view.inputmethod.Flags.refactorInsetsController()) {
-            notifyInsetsChanged();
-            mDisplayContent.updateSystemGestureExclusion();
-            mDisplayContent.getDisplayPolicy().updateSystemBarAttributes();
-        }
     }
 
     void notifySurfaceTransactionReady(InsetsSourceProvider provider, long id, boolean ready) {
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index ca47133..29c0c7b 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -22,6 +22,7 @@
 import static android.window.TaskConstants.TASK_CHILD_LAYER_TASK_OVERLAY;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -174,11 +175,12 @@
     public void destroy() {
         mOuter.setEmpty();
         mInner.setEmpty();
-
+        final SurfaceControl.Transaction tx = mTransactionFactory.get();
         for (LetterboxSurface surface : mSurfaces) {
-            surface.remove();
+            surface.remove(tx);
         }
-        mFullWindowSurface.remove();
+        mFullWindowSurface.remove(tx);
+        tx.apply();
     }
 
     /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */
@@ -196,30 +198,19 @@
 
     /** Applies surface changes such as colour, window crop, position and input info. */
     public void applySurfaceChanges(@NonNull SurfaceControl.Transaction t,
-            @NonNull SurfaceControl.Transaction inputT) {
+            @NonNull SurfaceControl.Transaction inputT, @NonNull WindowState windowState) {
         if (useFullWindowSurface()) {
+            for (LetterboxSurface surface : mSurfaces) {
+                surface.remove(t);
+            }
+            mFullWindowSurface.attachInput(windowState);
             mFullWindowSurface.applySurfaceChanges(t, inputT);
-
-            for (LetterboxSurface surface : mSurfaces) {
-                surface.remove();
-            }
         } else {
+            mFullWindowSurface.remove(t);
             for (LetterboxSurface surface : mSurfaces) {
+                surface.attachInput(windowState);
                 surface.applySurfaceChanges(t, inputT);
             }
-
-            mFullWindowSurface.remove();
-        }
-    }
-
-    /** Enables touches to slide into other neighboring surfaces. */
-    void attachInput(WindowState win) {
-        if (useFullWindowSurface()) {
-            mFullWindowSurface.attachInput(win);
-        } else {
-            for (LetterboxSurface surface : mSurfaces) {
-                surface.attachInput(win);
-            }
         }
     }
 
@@ -358,9 +349,10 @@
         private final Rect mLayoutFrameGlobal = new Rect();
         private final Rect mLayoutFrameRelative = new Rect();
 
+        @Nullable
         private InputInterceptor mInputInterceptor;
 
-        public LetterboxSurface(String type) {
+        LetterboxSurface(@NonNull String type) {
             mType = type;
         }
 
@@ -394,28 +386,28 @@
             t.setLayer(mInputSurface, TASK_CHILD_LAYER_TASK_OVERLAY);
         }
 
-        void attachInput(WindowState win) {
-            if (mInputInterceptor != null) {
-                mInputInterceptor.dispose();
+        void attachInput(@NonNull WindowState windowState) {
+            if (mInputInterceptor != null || windowState.mDisplayContent == null) {
+                return;
             }
             // TODO(b/371179559): only detect double tap on LB surfaces not used for cutout area.
             // Potentially, the input interceptor may still be needed for slippery feature.
-            mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", win);
+            mInputInterceptor = new InputInterceptor("Letterbox_" + mType + "_", windowState);
         }
 
-        public void remove() {
-            if (mSurface != null) {
-                mTransactionFactory.get().remove(mSurface).apply();
-                mSurface = null;
-            }
-            if (mInputSurface != null) {
-                mTransactionFactory.get().remove(mInputSurface).apply();
-                mInputSurface = null;
-            }
+        void remove(@NonNull SurfaceControl.Transaction t) {
             if (mInputInterceptor != null) {
                 mInputInterceptor.dispose();
                 mInputInterceptor = null;
             }
+            if (mSurface != null) {
+                t.remove(mSurface);
+            }
+            if (mInputSurface != null) {
+                t.remove(mInputSurface);
+            }
+            mInputSurface = null;
+            mSurface = null;
         }
 
         public int getWidth() {
diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS
index 98521d3..dede767 100644
--- a/services/core/java/com/android/server/wm/OWNERS
+++ b/services/core/java/com/android/server/wm/OWNERS
@@ -21,6 +21,7 @@
 pdwilliams@google.com
 charlesccchen@google.com
 marziana@google.com
+mcarli@google.com
 
 # Files related to background activity launches
 per-file Background*Start* = set noparent
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 7fdc2c6..44f000d 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1515,9 +1515,9 @@
             boolean skipExcludedCheck) {
         if (!skipExcludedCheck) {
             // Keep the most recent task of home display even if it is excluded from recents.
-            final boolean isExcludeFromRecents =
-                    (task.getBaseIntent().getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
-                            == FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+            final boolean isExcludeFromRecents = task.getBaseIntent() != null
+                    && (task.getBaseIntent().getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+                    == FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
             if (isExcludeFromRecents) {
                 if (DEBUG_RECENTS_TRIM_TASKS) {
                     Slog.d(TAG,
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3d28685..4f36476 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1941,7 +1941,8 @@
         if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
             final IntArray visibleRootTasks = new IntArray();
             forAllRootTasks(rootTask -> {
-                if (mCurrentUser == rootTask.mUserId && rootTask.isVisibleRequested()) {
+                if ((mCurrentUser == rootTask.mUserId || rootTask.showForAllUsers())
+                        && rootTask.isVisible()) {
                     visibleRootTasks.add(rootTask.getRootTaskId());
                 }
             }, /* traverseTopToBottom */ false);
@@ -2045,6 +2046,11 @@
 
             if (Flags.enableTopVisibleRootTaskPerUserTracking()) {
                 final IntArray rootTasks = mUserVisibleRootTasks.get(userId, new IntArray());
+                // If root task already exists in the list, move it to the top instead.
+                final int rootTaskIndex = rootTasks.indexOf(rootTask.getRootTaskId());
+                if (rootTaskIndex != -1) {
+                    rootTasks.remove(rootTaskIndex);
+                }
                 rootTasks.add(rootTask.getRootTaskId());
                 mUserVisibleRootTasks.put(userId, rootTasks);
             } else {
@@ -2926,7 +2932,6 @@
     }
 
     void prepareForShutdown() {
-        mWindowManager.mSnapshotController.mTaskSnapshotController.prepareShutdown();
         for (int i = 0; i < getChildCount(); i++) {
             createSleepToken("shutdown", getChildAt(i).mDisplayId);
         }
diff --git a/services/core/java/com/android/server/wm/ScreenRecordingCallbackController.java b/services/core/java/com/android/server/wm/ScreenRecordingCallbackController.java
index 38e0115..efc68aa 100644
--- a/services/core/java/com/android/server/wm/ScreenRecordingCallbackController.java
+++ b/services/core/java/com/android/server/wm/ScreenRecordingCallbackController.java
@@ -95,8 +95,9 @@
         if (mediaProjectionInfo.getLaunchCookie() == null) {
             mRecordedWC = (WindowContainer) mWms.mRoot.getDefaultDisplay();
         } else {
-            mRecordedWC = mWms.mRoot.getActivity(activity -> activity.mLaunchCookie
-                    == mediaProjectionInfo.getLaunchCookie().binder).getTask();
+            final ActivityRecord matchingActivity = mWms.mRoot.getActivity(activity ->
+                    activity.mLaunchCookie == mediaProjectionInfo.getLaunchCookie().binder);
+            mRecordedWC = matchingActivity != null ? matchingActivity.getTask() : null;
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 76d8861..d92301b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3652,14 +3652,6 @@
         // If the developer has persist a different configuration, we need to override it to the
         // starting window because persisted configuration does not effect to Task.
         info.taskInfo.configuration.setTo(activity.getConfiguration());
-        if (!Flags.drawSnapshotAspectRatioMatch()) {
-            final WindowState mainWindow = getTopFullscreenMainWindow();
-            if (mainWindow != null) {
-                info.topOpaqueWindowInsetsState =
-                        mainWindow.getInsetsStateWithVisibilityOverride();
-                info.topOpaqueWindowLayoutParams = mainWindow.getAttrs();
-            }
-        }
         return info;
     }
 
@@ -3715,10 +3707,21 @@
 
                 // Boost the adjacent TaskFragment for dimmer if needed.
                 final TaskFragment taskFragment = wc.asTaskFragment();
-                if (taskFragment != null && taskFragment.isEmbedded()) {
-                    final TaskFragment adjacentTf = taskFragment.getAdjacentTaskFragment();
-                    if (adjacentTf != null && adjacentTf.shouldBoostDimmer()) {
-                        adjacentTf.assignLayer(t, layer++);
+                if (taskFragment != null && taskFragment.isEmbedded()
+                        && taskFragment.hasAdjacentTaskFragment()) {
+                    if (Flags.allowMultipleAdjacentTaskFragments()) {
+                        final int[] nextLayer = { layer };
+                        taskFragment.forOtherAdjacentTaskFragments(adjacentTf -> {
+                            if (adjacentTf.shouldBoostDimmer()) {
+                                adjacentTf.assignLayer(t, nextLayer[0]++);
+                            }
+                        });
+                        layer = nextLayer[0];
+                    } else {
+                        final TaskFragment adjacentTf = taskFragment.getAdjacentTaskFragment();
+                        if (adjacentTf.shouldBoostDimmer()) {
+                            adjacentTf.assignLayer(t, layer++);
+                        }
                     }
                 }
 
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 9564c59..3d0b41b 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1045,7 +1045,7 @@
                                 + adjacentFlagRootTask);
             }
 
-            if (adjacentFlagRootTask.getAdjacentTaskFragment() == null) {
+            if (!adjacentFlagRootTask.hasAdjacentTaskFragment()) {
                 throw new UnsupportedOperationException(
                         "Can't set non-adjacent root as launch adjacent flag root tr="
                                 + adjacentFlagRootTask);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 38a2ebe..7d300e98 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -36,7 +36,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
 import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;
+import com.android.window.flags.Flags;
 
+import java.util.ArrayList;
 import java.util.Set;
 
 /**
@@ -154,6 +156,8 @@
      * The attributes of task snapshot are based on task configuration. But sometimes the
      * configuration may have been changed during a transition, so supply the ChangeInfo that
      * stored the previous appearance of the closing task.
+     *
+     * The snapshot won't be created immediately if it should be captured as fake snapshot.
      */
     void recordSnapshot(Task task, Transition.ChangeInfo changeInfo) {
         mCurrentChangeInfo = changeInfo;
@@ -164,13 +168,35 @@
         }
     }
 
-    TaskSnapshot recordSnapshot(Task task) {
-        final TaskSnapshot snapshot = recordSnapshotInner(task);
-        if (snapshot != null && !task.isActivityTypeHome()) {
-            mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
-            task.onSnapshotChanged(snapshot);
+    void recordSnapshot(Task task) {
+        if (shouldDisableSnapshots()) {
+            return;
         }
-        return snapshot;
+        final SnapshotSupplier supplier = getRecordSnapshotSupplier(task);
+        if (supplier == null) {
+            return;
+        }
+        final int mode = getSnapshotMode(task);
+        if (Flags.excludeDrawingAppThemeSnapshotFromLock() && mode == SNAPSHOT_MODE_APP_THEME) {
+            mService.mH.post(supplier::handleSnapshot);
+        } else {
+            supplier.handleSnapshot();
+        }
+    }
+
+    /**
+     * Note that the snapshot is not created immediately, if the returned supplier is non-null, the
+     * caller must call {@link AbsAppSnapshotController.SnapshotSupplier#get} or
+     * {@link AbsAppSnapshotController.SnapshotSupplier#handleSnapshot} to complete the entire
+     * record request.
+     */
+    SnapshotSupplier getRecordSnapshotSupplier(Task task) {
+        return recordSnapshotInner(task, true /* allowAppTheme */, snapshot -> {
+            if (!task.isActivityTypeHome()) {
+                mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
+                task.onSnapshotChanged(snapshot);
+            }
+        });
     }
 
     /**
@@ -328,27 +354,38 @@
      * Record task snapshots before shutdown.
      */
     void prepareShutdown() {
-        if (!com.android.window.flags.Flags.recordTaskSnapshotsBeforeShutdown()) {
+        if (!Flags.recordTaskSnapshotsBeforeShutdown()) {
             return;
         }
-        // Make write items run in a batch.
-        mPersister.mSnapshotPersistQueue.setPaused(true);
-        mPersister.mSnapshotPersistQueue.prepareShutdown();
-        for (int i = 0; i < mService.mRoot.getChildCount(); i++) {
-            mService.mRoot.getChildAt(i).forAllLeafTasks(task -> {
-                if (task.isVisible() && !task.isActivityTypeHome()) {
-                    final TaskSnapshot snapshot = captureSnapshot(task);
-                    if (snapshot != null) {
-                        mPersister.persistSnapshot(task.mTaskId, task.mUserId, snapshot);
+        final ArrayList<SnapshotSupplier> supplierArrayList = new ArrayList<>();
+        synchronized (mService.mGlobalLock) {
+            // Make write items run in a batch.
+            mPersister.mSnapshotPersistQueue.setPaused(true);
+            mPersister.mSnapshotPersistQueue.prepareShutdown();
+            for (int i = 0; i < mService.mRoot.getChildCount(); i++) {
+                mService.mRoot.getChildAt(i).forAllLeafTasks(task -> {
+                    if (task.isVisible() && !task.isActivityTypeHome()) {
+                        final SnapshotSupplier supplier = captureSnapshot(task,
+                                true /* allowAppTheme */);
+                        if (supplier != null) {
+                            supplier.setConsumer(t ->
+                                    mPersister.persistSnapshot(task.mTaskId, task.mUserId, t));
+                            supplierArrayList.add(supplier);
+                        }
                     }
-                }
-            }, true /* traverseTopToBottom */);
+                }, true /* traverseTopToBottom */);
+            }
         }
-        mPersister.mSnapshotPersistQueue.setPaused(false);
+        for (int i = supplierArrayList.size() - 1; i >= 0; --i) {
+            supplierArrayList.get(i).handleSnapshot();
+        }
+        synchronized (mService.mGlobalLock) {
+            mPersister.mSnapshotPersistQueue.setPaused(false);
+        }
     }
 
     void waitFlush(long timeout) {
-        if (!com.android.window.flags.Flags.recordTaskSnapshotsBeforeShutdown()) {
+        if (!Flags.recordTaskSnapshotsBeforeShutdown()) {
             return;
         }
         mPersister.mSnapshotPersistQueue.waitFlush(timeout);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 1f539a1..a3d71db 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1589,7 +1589,7 @@
         cleanUpInternal();
 
         // Handle back animation if it's already started.
-        mController.mAtm.mBackNavigationController.onTransitionFinish(mTargets, this);
+        mController.mAtm.mBackNavigationController.onTransitionFinish(this);
         mController.mFinishingTransition = null;
         mController.mSnapshotController.onTransitionFinish(mType, mTargets);
         // Resume snapshot persist thread after snapshot controller analysis this transition.
@@ -2542,15 +2542,16 @@
             // TaskFragment doesn't contain occluded ActivityRecord.
             return true;
         }
-        final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
-        if (adjacentTaskFragment != null) {
-            // When the TaskFragment has an adjacent TaskFragment, sibling behind them should be
-            // hidden unless any of them are translucent.
-            return adjacentTaskFragment.isTranslucentForTransition();
-        } else {
+        if (!taskFragment.hasAdjacentTaskFragment()) {
             // Non-filling without adjacent is considered as translucent.
             return !wc.fillsParent();
         }
+        // When the TaskFragment has an adjacent TaskFragment, sibling behind them should be
+        // hidden unless any of them are translucent.
+        if (!Flags.allowMultipleAdjacentTaskFragments()) {
+            return taskFragment.getAdjacentTaskFragment().isTranslucentForTransition();
+        }
+        return taskFragment.forOtherAdjacentTaskFragments(TaskFragment::isTranslucentForTransition);
     }
 
     private void updatePriorVisibility() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9d9c53d..793f189 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -121,6 +121,7 @@
 import static com.android.server.LockGuard.installLock;
 import static com.android.server.policy.PhoneWindowManager.TRACE_WAIT_FOR_ALL_WINDOWS_DRAWN_METHOD;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ActivityTaskManagerService.DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
 import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND;
 import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
@@ -2945,7 +2946,7 @@
                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
                 if (dc == null) {
                     if (callingPid != MY_PID) {
-                        throw new WindowManager.InvalidDisplayException(
+                        throw new IllegalArgumentException(
                                 "attachWindowContextToDisplayContent: trying to attach to a"
                                         + " non-existing display:" + displayId);
                     }
@@ -7845,6 +7846,37 @@
     }
 
     @Override
+    public void onNotificationShadeExpanded(IBinder token, boolean expanded) {
+        synchronized (mGlobalLock) {
+            final WindowState w = mWindowMap.get(token);
+            if (w == null || w != w.mDisplayContent.getDisplayPolicy().getNotificationShade()) {
+                return;
+            }
+            final WindowProcessController topApp = mAtmService.mTopApp;
+            // Demotes the priority of top app if notification shade is expanded to occlude the app.
+            // So the notification shade may have more capacity to draw and animate.
+            final int demoteTopAppReasons = mAtmService.mDemoteTopAppReasons;
+            if (expanded && mAtmService.mTopProcessState == ActivityManager.PROCESS_STATE_TOP
+                    && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) == 0) {
+                mAtmService.mDemoteTopAppReasons =
+                        demoteTopAppReasons | DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
+                Trace.instant(TRACE_TAG_WINDOW_MANAGER, "demote-top-for-ns");
+                if (topApp != null) {
+                    topApp.scheduleUpdateOomAdj();
+                }
+            } else if (!expanded
+                    && (demoteTopAppReasons & DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE) != 0) {
+                mAtmService.mDemoteTopAppReasons =
+                        demoteTopAppReasons & ~DEMOTE_TOP_REASON_EXPANDED_NOTIFICATION_SHADE;
+                Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancel-demote-top-for-ns");
+                if (topApp != null) {
+                    topApp.scheduleUpdateOomAdj();
+                }
+            }
+        }
+    }
+
+    @Override
     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
             throws RemoteException {
         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
@@ -10084,14 +10116,16 @@
         TaskSnapshot taskSnapshot;
         final long token = Binder.clearCallingIdentity();
         try {
+            final Supplier<TaskSnapshot> supplier;
             synchronized (mGlobalLock) {
                 Task task = mRoot.anyTaskForId(taskId, MATCH_ATTACHED_TASK_OR_RECENT_TASKS);
                 if (task == null) {
                     throw new IllegalArgumentException(
                             "Failed to find matching task for taskId=" + taskId);
                 }
-                taskSnapshot = mTaskSnapshotController.captureSnapshot(task);
+                supplier = mTaskSnapshotController.captureSnapshot(task, true /* allowAppTheme */);
             }
+            taskSnapshot = supplier != null ? supplier.get() : null;
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index fb197c5..e45ada9 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -80,6 +80,7 @@
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
+import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
@@ -716,6 +717,8 @@
                 }
                 if (forceHiddenForPip) {
                     wc.asTask().setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
+                }
+                if (forceHiddenForPip && !isPip2ExperimentEnabled()) {
                     // When removing pip, make sure that onStop is sent to the app ahead of
                     // onPictureInPictureModeChanged.
                     // See also PinnedStackTests#testStopBeforeMultiWindowCallbacksOnDismiss
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 68b4b6f..b43e334 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5750,9 +5750,10 @@
                 || mKeyInterceptionInfo.layoutParamsPrivateFlags != getAttrs().privateFlags
                 || mKeyInterceptionInfo.layoutParamsType != getAttrs().type
                 || mKeyInterceptionInfo.windowTitle != getWindowTag()
-                || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()) {
+                || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()
+                || mKeyInterceptionInfo.inputFeaturesFlags != getAttrs().inputFeatures) {
             mKeyInterceptionInfo = new KeyInterceptionInfo(getAttrs().type, getAttrs().privateFlags,
-                    getWindowTag().toString(), getOwningUid());
+                    getWindowTag().toString(), getOwningUid(), getAttrs().inputFeatures);
         }
         return mKeyInterceptionInfo;
     }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 01639cc..d26539c 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -80,6 +80,7 @@
         ":lib_oomConnection_native",
         ":lib_anrTimer_native",
         ":lib_lazilyRegisteredServices_native",
+        ":lib_phantomProcessList_native",
     ],
 
     include_dirs: [
@@ -265,3 +266,10 @@
         "com_android_server_vr_VrManagerService.cpp",
     ],
 }
+
+filegroup {
+    name: "lib_phantomProcessList_native",
+    srcs: [
+        "com_android_server_am_PhantomProcessList.cpp",
+    ],
+}
diff --git a/services/core/jni/com_android_server_am_PhantomProcessList.cpp b/services/core/jni/com_android_server_am_PhantomProcessList.cpp
new file mode 100644
index 0000000..0c5e6d8
--- /dev/null
+++ b/services/core/jni/com_android_server_am_PhantomProcessList.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <processgroup/processgroup.h>
+
+namespace android {
+namespace {
+
+jstring getCgroupProcsPath(JNIEnv* env, jobject clazz, jint uid, jint pid) {
+    if (uid < 0) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "uid is negative: %d", uid);
+        return nullptr;
+    }
+
+    std::string path;
+    if (!CgroupGetAttributePathForProcess("CgroupProcs", uid, pid, path)) {
+        path.clear();
+    }
+
+    return env->NewStringUTF(path.c_str());
+}
+
+const JNINativeMethod sMethods[] = {
+        {"nativeGetCgroupProcsPath", "(II)Ljava/lang/String;", (void*)getCgroupProcsPath},
+};
+
+} // anonymous namespace
+
+int register_android_server_am_PhantomProcessList(JNIEnv* env) {
+    const char* className = "com/android/server/am/PhantomProcessList";
+    return jniRegisterNativeMethods(env, className, sMethods, NELEM(sMethods));
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 0464230..813fec1 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -343,6 +343,7 @@
     void setPointerSpeed(int32_t speed);
     void setMousePointerAccelerationEnabled(ui::LogicalDisplayId displayId, bool enabled);
     void setMouseReverseVerticalScrollingEnabled(bool enabled);
+    void setMouseScrollingAccelerationEnabled(bool enabled);
     void setMouseSwapPrimaryButtonEnabled(bool enabled);
     void setTouchpadPointerSpeed(int32_t speed);
     void setTouchpadNaturalScrollingEnabled(bool enabled);
@@ -492,6 +493,9 @@
         // True if stylus button reporting through motion events is enabled.
         bool stylusButtonMotionEventsEnabled{true};
 
+        // True if mouse scrolling acceleration is enabled.
+        bool mouseScrollingAccelerationEnabled{true};
+
         // True if mouse vertical scrolling is reversed.
         bool mouseReverseVerticalScrollingEnabled{false};
 
@@ -553,6 +557,9 @@
     PointerIcon loadPointerIcon(JNIEnv* env, ui::LogicalDisplayId displayId, PointerIconStyle type);
     bool isDisplayInteractive(ui::LogicalDisplayId displayId);
 
+    // TODO(b/362719483) remove when the real topology is available
+    void populateFakeDisplayTopology(const std::vector<DisplayViewport>& viewports);
+
     static inline JNIEnv* jniEnv() { return AndroidRuntime::getJNIEnv(); }
 };
 
@@ -641,6 +648,49 @@
     mInputManager->getChoreographer().setDisplayViewports(viewports);
     mInputManager->getReader().requestRefreshConfiguration(
             InputReaderConfiguration::Change::DISPLAY_INFO);
+
+    // TODO(b/362719483) remove when the real topology is available
+    populateFakeDisplayTopology(viewports);
+}
+
+void NativeInputManager::populateFakeDisplayTopology(
+        const std::vector<DisplayViewport>& viewports) {
+    if (!com::android::input::flags::connected_displays_cursor()) {
+        return;
+    }
+
+    // create a fake topology assuming following order
+    // default-display (top-edge) -> next-display (right-edge) -> next-display (right-edge) ...
+    // This also adds a 100px offset on corresponding edge for better manual testing
+    //   ┌────────┐
+    //   │ next   ├─────────┐
+    // ┌─└───────┐┤ next 2  │ ...
+    // │ default │└─────────┘
+    // └─────────┘
+    DisplayTopologyGraph displaytopology;
+    displaytopology.primaryDisplayId = ui::LogicalDisplayId::DEFAULT;
+
+    // treat default display as base, in real topology it should be the primary-display
+    ui::LogicalDisplayId previousDisplay = ui::LogicalDisplayId::DEFAULT;
+    for (const auto& viewport : viewports) {
+        if (viewport.displayId == ui::LogicalDisplayId::DEFAULT) {
+            continue;
+        }
+        if (previousDisplay == ui::LogicalDisplayId::DEFAULT) {
+            displaytopology.graph[previousDisplay].push_back(
+                    {viewport.displayId, DisplayTopologyPosition::TOP, 100});
+            displaytopology.graph[viewport.displayId].push_back(
+                    {previousDisplay, DisplayTopologyPosition::BOTTOM, -100});
+        } else {
+            displaytopology.graph[previousDisplay].push_back(
+                    {viewport.displayId, DisplayTopologyPosition::RIGHT, 100});
+            displaytopology.graph[viewport.displayId].push_back(
+                    {previousDisplay, DisplayTopologyPosition::LEFT, -100});
+        }
+        previousDisplay = viewport.displayId;
+    }
+
+    mInputManager->getChoreographer().setDisplayTopology(displaytopology);
 }
 
 void NativeInputManager::setDisplayTopology(JNIEnv* env, jobject topologyGraph) {
@@ -782,6 +832,10 @@
                         mLocked.pointerDisplayId) == 0
                 ? android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION
                 : 1;
+        outConfig->wheelVelocityControlParameters.acceleration =
+                mLocked.mouseScrollingAccelerationEnabled
+                ? android::os::IInputConstants::DEFAULT_MOUSE_WHEEL_ACCELERATION
+                : 1;
         outConfig->pointerGesturesEnabled = mLocked.pointerGesturesEnabled;
 
         outConfig->pointerCaptureRequest = mLocked.pointerCaptureRequest;
@@ -1374,6 +1428,21 @@
             InputReaderConfiguration::Change::MOUSE_SETTINGS);
 }
 
+void NativeInputManager::setMouseScrollingAccelerationEnabled(bool enabled) {
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+
+        if (mLocked.mouseScrollingAccelerationEnabled == enabled) {
+            return;
+        }
+
+        mLocked.mouseScrollingAccelerationEnabled = enabled;
+    } // release lock
+
+    mInputManager->getReader().requestRefreshConfiguration(
+            InputReaderConfiguration::Change::POINTER_SPEED);
+}
+
 void NativeInputManager::setMouseSwapPrimaryButtonEnabled(bool enabled) {
     { // acquire lock
         std::scoped_lock _l(mLock);
@@ -3133,6 +3202,12 @@
     return static_cast<jint>(im->getInputManager()->getReader().getLastUsedInputDeviceId());
 }
 
+static void nativeSetMouseScrollingAccelerationEnabled(JNIEnv* env, jobject nativeImplObj,
+                                                       bool enabled) {
+    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
+    im->setMouseScrollingAccelerationEnabled(enabled);
+}
+
 static void nativeSetMouseReverseVerticalScrollingEnabled(JNIEnv* env, jobject nativeImplObj,
                                                           bool enabled) {
     NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
@@ -3202,6 +3277,8 @@
          (void*)nativeSetMousePointerAccelerationEnabled},
         {"setMouseReverseVerticalScrollingEnabled", "(Z)V",
          (void*)nativeSetMouseReverseVerticalScrollingEnabled},
+        {"setMouseScrollingAccelerationEnabled", "(Z)V",
+         (void*)nativeSetMouseScrollingAccelerationEnabled},
         {"setMouseSwapPrimaryButtonEnabled", "(Z)V", (void*)nativeSetMouseSwapPrimaryButtonEnabled},
         {"setTouchpadPointerSpeed", "(I)V", (void*)nativeSetTouchpadPointerSpeed},
         {"setTouchpadNaturalScrollingEnabled", "(Z)V",
diff --git a/services/core/jni/com_android_server_tv_TvKeys.h b/services/core/jni/com_android_server_tv_TvKeys.h
index b3ee263..babdb4c 100644
--- a/services/core/jni/com_android_server_tv_TvKeys.h
+++ b/services/core/jni/com_android_server_tv_TvKeys.h
@@ -91,8 +91,11 @@
         {KEY_TEXT, AKEYCODE_TV_TELETEXT},
         {KEY_SUBTITLE, AKEYCODE_CAPTIONS},
         {KEY_PVR, AKEYCODE_DVR},
+        {KEY_VIDEO, AKEYCODE_TV_INPUT},
         {KEY_AUDIO, AKEYCODE_MEDIA_AUDIO_TRACK},
+        {KEY_AUDIO_DESC, AKEYCODE_TV_AUDIO_DESCRIPTION},
         {KEY_OPTION, AKEYCODE_SETTINGS},
+        {KEY_DOT,  AKEYCODE_PERIOD},
 
         // Gamepad buttons
         {KEY_UP, AKEYCODE_DPAD_UP},
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index e3bd69c..569383e 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -72,6 +72,7 @@
 int register_com_android_server_SystemClockTime(JNIEnv* env);
 int register_android_server_display_smallAreaDetectionController(JNIEnv* env);
 int register_com_android_server_accessibility_BrailleDisplayConnection(JNIEnv* env);
+int register_android_server_am_PhantomProcessList(JNIEnv* env);
 
 // Note: Consider adding new JNI entrypoints for optional services to
 // LazyJniRegistrar instead, and relying on lazy registration.
@@ -139,5 +140,6 @@
     register_com_android_server_SystemClockTime(env);
     register_android_server_display_smallAreaDetectionController(env);
     register_com_android_server_accessibility_BrailleDisplayConnection(env);
+    register_android_server_am_PhantomProcessList(env);
     return JNI_VERSION_1_4;
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 60130d1..9ab9a8f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -91,6 +91,7 @@
 import android.system.ErrnoException;
 import android.system.Os;
 import android.text.TextUtils;
+import android.tracing.perfetto.InitArguments;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.Dumpable;
@@ -440,7 +441,7 @@
             "/apex/com.android.uwb/javalib/service-uwb.jar";
     private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
     private static final String BLUETOOTH_APEX_SERVICE_JAR_PATH =
-            "/apex/com.android.btservices/javalib/service-bluetooth.jar";
+            "/apex/com.android.bt/javalib/service-bluetooth.jar";
     private static final String BLUETOOTH_SERVICE_CLASS =
             "com.android.server.bluetooth.BluetoothService";
     private static final String DEVICE_LOCK_SERVICE_CLASS =
@@ -792,6 +793,12 @@
     private void run() {
         TimingsTraceAndSlog t = new TimingsTraceAndSlog();
         try {
+            if (android.tracing.Flags.systemServerLargePerfettoShmemBuffer()) {
+                // Explicitly initialize a 4 MB shmem buffer for Perfetto producers (b/382369925)
+                android.tracing.perfetto.Producer.init(new InitArguments(
+                        InitArguments.PERFETTO_BACKEND_SYSTEM, 4 * 1024));
+            }
+
             t.traceBegin("InitBeforeStartServices");
 
             // Record the process start information in sys props.
@@ -3114,10 +3121,10 @@
         if (com.android.ranging.flags.Flags.rangingStackEnabled()) {
             if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)
                     || context.getPackageManager().hasSystemFeature(
-                            PackageManager.FEATURE_WIFI_RTT)
+                            PackageManager.FEATURE_WIFI_AWARE)
                     || (com.android.ranging.flags.Flags.rangingCsEnabled()
                             && context.getPackageManager().hasSystemFeature(
-                                    PackageManager.FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING))) {
+                                    PackageManager.FEATURE_BLUETOOTH_LE))) {
                 t.traceBegin("RangingService");
                 // TODO: b/375264320 - Remove after RELEASE_RANGING_STACK is ramped to next.
                 try {
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index 161a816..b356b83 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -119,6 +119,10 @@
         val permissions = service.getState { with(permissionPolicy) { getPermissions() } }
 
         for (appOpCode in 0 until AppOpsManager._NUM_OP) {
+            // Ops that default to MODE_FOREGROUND are foregroundable.
+            if (AppOpsManager.opToDefaultMode(appOpCode) == AppOpsManager.MODE_FOREGROUND) {
+                foregroundableOps[appOpCode] = true
+            }
             AppOpsManager.opToPermission(appOpCode)?.let { permissionName ->
                 // Multiple ops might map to a single permission but only one is considered the
                 // runtime appop calculations.
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index d2c91ff..232bb83 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -286,14 +286,21 @@
                 return@forEach
             }
             var newFlags = oldFlags
+            val isSystemOrInstalled =
+                packageState.isSystem || packageState.getUserStateOrDefault(userId).isInstalled
             newFlags =
                 if (
-                    newFlags.hasBits(PermissionFlags.ROLE) ||
-                        newFlags.hasBits(PermissionFlags.PREGRANT)
+                    isSystemOrInstalled && (
+                        newFlags.hasBits(PermissionFlags.ROLE) ||
+                            newFlags.hasBits(PermissionFlags.PREGRANT)
+                    )
                 ) {
                     newFlags or PermissionFlags.RUNTIME_GRANTED
                 } else {
-                    newFlags andInv PermissionFlags.RUNTIME_GRANTED
+                    newFlags andInv (
+                        PermissionFlags.RUNTIME_GRANTED or PermissionFlags.ROLE or
+                            PermissionFlags.PREGRANT
+                    )
                 }
             newFlags = newFlags andInv USER_SETTABLE_MASK
             if (newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)) {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index c31594a..fc585c9 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.profcollect;
 
+import static android.content.Intent.ACTION_BATTERY_LOW;
+import static android.content.Intent.ACTION_BATTERY_OKAY;
 import static android.content.Intent.ACTION_SCREEN_OFF;
 import static android.content.Intent.ACTION_SCREEN_ON;
 
@@ -77,6 +79,7 @@
     static boolean sVerityEnforced;
     static boolean sIsInteractive;
     static boolean sAdbActive;
+    static boolean sIsBatteryLow;
 
     private static IProfCollectd sIProfcollect;
     private static ProfcollectForwardingService sSelfService;
@@ -91,7 +94,11 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (ACTION_SCREEN_ON.equals(intent.getAction())) {
+            if (ACTION_BATTERY_LOW.equals(intent.getAction())) {
+                sIsBatteryLow = true;
+            } else if (ACTION_BATTERY_OKAY.equals(intent.getAction())) {
+                sIsBatteryLow = false;
+            } else if (ACTION_SCREEN_ON.equals(intent.getAction())) {
                 Log.d(LOG_TAG, "Received broadcast that the device became interactive, was "
                         + sIsInteractive);
                 sIsInteractive = true;
@@ -141,6 +148,8 @@
             context.getResources().getBoolean(R.bool.config_profcollectReportUploaderEnabled);
 
         final IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_BATTERY_LOW);
+        filter.addAction(ACTION_BATTERY_OKAY);
         filter.addAction(ACTION_SCREEN_ON);
         filter.addAction(ACTION_SCREEN_OFF);
         filter.addAction(INTENT_UPLOAD_PROFILES);
diff --git a/services/profcollect/src/com/android/server/profcollect/Utils.java b/services/profcollect/src/com/android/server/profcollect/Utils.java
index b754ca1..c109f5cf 100644
--- a/services/profcollect/src/com/android/server/profcollect/Utils.java
+++ b/services/profcollect/src/com/android/server/profcollect/Utils.java
@@ -118,6 +118,7 @@
         }
         return ProfcollectForwardingService.sVerityEnforced
             && !ProfcollectForwardingService.sAdbActive
-            && ProfcollectForwardingService.sIsInteractive;
+            && ProfcollectForwardingService.sIsInteractive
+            && !ProfcollectForwardingService.sIsBatteryLow;
     }
 }
diff --git a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index fc3ec7b..4d04c8b 100644
--- a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -37,6 +37,7 @@
 import android.util.Log;
 
 import com.android.server.backup.BackupAgentTimeoutParameters;
+import com.android.server.backup.BackupManagerConstants;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.UserBackupManagerService;
@@ -162,10 +163,10 @@
 
     public static UserBackupManagerService.BackupWakeLock createBackupWakeLock(
             Application application) {
-        PowerManager powerManager =
-                (PowerManager) application.getSystemService(Context.POWER_SERVICE);
+        PowerManager powerManager = application.getSystemService(PowerManager.class);
         return new UserBackupManagerService.BackupWakeLock(
-                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"), 0);
+                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"), 0,
+                new BackupManagerConstants(Handler.getMain(), application.getContentResolver()));
     }
 
     /**
diff --git a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt
index 1237095..8b357862d 100644
--- a/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt
+++ b/services/tests/PermissionServiceMockingTests/src/com/android/server/permission/test/AppIdPermissionPolicyPermissionResetTest.kt
@@ -72,7 +72,8 @@
         } else {
             mockPackageState(
                 APP_ID_1,
-                mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0))
+                mockAndroidPackage(PACKAGE_NAME_1, requestedPermissions = setOf(PERMISSION_NAME_0)),
+                true
             )
         }
         setPermissionFlags(APP_ID_1, USER_ID_0, PERMISSION_NAME_0, oldFlags)
diff --git a/services/tests/appfunctions/Android.bp b/services/tests/appfunctions/Android.bp
index 836f90b..e48abc2 100644
--- a/services/tests/appfunctions/Android.bp
+++ b/services/tests/appfunctions/Android.bp
@@ -33,18 +33,20 @@
     ],
 
     static_libs: [
-        "androidx.test.core",
-        "androidx.test.runner",
-        "androidx.test.ext.truth",
         "androidx.core_core-ktx",
+        "androidx.test.core",
+        "androidx.test.ext.truth",
+        "androidx.test.rules",
+        "androidx.test.runner",
+        "frameworks-base-testutils",
         "kotlin-test",
         "kotlinx_coroutines_test",
+        "mockito-kotlin2",
+        "mockito-target-extended-minus-junit4",
         "platform-test-annotations",
         "services.appfunctions",
         "servicestests-core-utils",
         "truth",
-        "frameworks-base-testutils",
-        "androidx.test.rules",
     ],
 
     libs: [
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt
new file mode 100644
index 0000000..896d2a21d
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/AppFunctionsLoggingTest.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appfunctions
+
+import android.app.appfunctions.AppFunctionException
+import android.app.appfunctions.ExecuteAppFunctionAidlRequest
+import android.app.appfunctions.ExecuteAppFunctionRequest
+import android.app.appfunctions.ExecuteAppFunctionResponse
+import android.app.appfunctions.IAppFunctionService
+import android.app.appfunctions.IExecuteAppFunctionCallback
+import android.app.appfunctions.SafeOneTimeExecuteAppFunctionCallback
+import android.app.appsearch.GenericDocument
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.UserHandle
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+
+
+/**
+ * Tests that AppFunctionsStatsLog logs AppFunctionsRequestReported with the expected values.
+ */
+@RunWith(AndroidJUnit4::class)
+class AppFunctionsLoggingTest {
+    @get:Rule
+    val mExtendedMockitoRule: ExtendedMockitoRule =
+        ExtendedMockitoRule.Builder(this)
+            .mockStatic(AppFunctionsStatsLog::class.java)
+            .build()
+    private val mContext: Context get() = ApplicationProvider.getApplicationContext()
+    private val mMockPackageManager = mock<PackageManager>()
+    private val mAppFunctionsLoggerWrapper =
+        AppFunctionsLoggerWrapper(
+            mMockPackageManager,
+            MoreExecutors.directExecutor(),
+            { TEST_CURRENT_TIME_MILLIS })
+    private lateinit var mSafeCallback: SafeOneTimeExecuteAppFunctionCallback
+
+    private val mServiceImpl =
+        AppFunctionManagerServiceImpl(
+            mContext,
+            mock<RemoteServiceCaller<IAppFunctionService>>(),
+            mock<CallerValidator>(),
+            mock<ServiceHelper>(),
+            ServiceConfigImpl(),
+            mAppFunctionsLoggerWrapper)
+
+    private val mRequestInternal = ExecuteAppFunctionAidlRequest(
+        ExecuteAppFunctionRequest.Builder(TEST_TARGET_PACKAGE, TEST_FUNCTION_ID).build(),
+        UserHandle.CURRENT, TEST_CALLING_PKG, TEST_INITIAL_REQUEST_TIME_MILLIS
+    )
+
+    @Before
+    fun setup() {
+        whenever(mMockPackageManager.getPackageUid(eq(TEST_TARGET_PACKAGE), any<Int>())).thenReturn(TEST_TARGET_UID)
+        mSafeCallback = mServiceImpl.initializeSafeExecuteAppFunctionCallback(mRequestInternal, mock<IExecuteAppFunctionCallback>(), TEST_CALLING_UID)
+        mSafeCallback.setExecutionStartTimeAfterBindMillis(TEST_EXECUTION_TIME_AFTER_BIND_MILLIS)
+    }
+
+    @Test
+    fun testOnSuccess_logsSuccessResponse() {
+        val response =
+            ExecuteAppFunctionResponse(GenericDocument.Builder<GenericDocument.Builder<*>>("", "", "")
+                .setPropertyLong("longProperty", 42L).setPropertyString("stringProperty", "text").build())
+
+        mSafeCallback.onResult(response)
+
+        ExtendedMockito.verify {
+            AppFunctionsStatsLog.write(
+                /* atomId= */ eq<Int>(AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED),
+                /* callerPackageUid= */ eq<Int>(TEST_CALLING_UID),
+                /* targetPackageUid= */ eq<Int>(TEST_TARGET_UID),
+                /* errorCode= */ eq<Int>(AppFunctionsLoggerWrapper.SUCCESS_RESPONSE_CODE),
+                /* requestSizeBytes= */ eq<Int>(mRequestInternal.clientRequest.requestDataSize),
+                /* responseSizeBytes= */ eq<Int>(response.responseDataSize),
+                /* requestDurationMs= */ eq<Long>(TEST_EXPECTED_E2E_DURATION_MILLIS),
+                /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS)
+            )
+        }
+    }
+
+    @Test
+    fun testOnError_logsFailureResponse() {
+        mSafeCallback.onError(AppFunctionException(AppFunctionException.ERROR_DENIED, "Error: permission denied"))
+
+        ExtendedMockito.verify {
+            AppFunctionsStatsLog.write(
+                /* atomId= */ eq<Int>(AppFunctionsStatsLog.APP_FUNCTIONS_REQUEST_REPORTED),
+                /* callerPackageUid= */ eq<Int>(TEST_CALLING_UID),
+                /* targetPackageUid= */ eq<Int>(TEST_TARGET_UID),
+                /* errorCode= */ eq<Int>(AppFunctionException.ERROR_DENIED),
+                /* requestSizeBytes= */ eq<Int>(mRequestInternal.clientRequest.requestDataSize),
+                /* responseSizeBytes= */ eq<Int>(0),
+                /* requestDurationMs= */ eq<Long>(TEST_EXPECTED_E2E_DURATION_MILLIS),
+                /* requestOverheadMs= */ eq<Long>(TEST_EXPECTED_OVERHEAD_DURATION_MILLIS)
+            )
+        }
+    }
+
+    private companion object {
+        const val TEST_CALLING_PKG = "com.android.trusted.caller"
+        const val TEST_CALLING_UID = 12345
+        const val TEST_TARGET_PACKAGE = "com.android.trusted.target"
+        const val TEST_TARGET_UID = 54321
+        const val TEST_FUNCTION_ID = "com.android.valid.target.doSomething"
+
+        const val TEST_INITIAL_REQUEST_TIME_MILLIS = 10L
+        const val TEST_EXECUTION_TIME_AFTER_BIND_MILLIS = 20L
+        const val TEST_CURRENT_TIME_MILLIS = 50L
+        const val TEST_EXPECTED_E2E_DURATION_MILLIS =
+            TEST_CURRENT_TIME_MILLIS - TEST_INITIAL_REQUEST_TIME_MILLIS
+        const val TEST_EXPECTED_OVERHEAD_DURATION_MILLIS =
+            TEST_EXECUTION_TIME_AFTER_BIND_MILLIS - TEST_INITIAL_REQUEST_TIME_MILLIS
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
index a8708f9..3449c36 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessSynchronizerTest.java
@@ -224,7 +224,7 @@
         mSynchronizer.startSynchronizing();
         verify(mDisplayManagerMock).registerDisplayListener(mDisplayListenerCaptor.capture(),
                 isA(Handler.class), eq(0L),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         mDisplayListener = mDisplayListenerCaptor.getValue();
 
         verify(mContentResolverSpy).registerContentObserver(eq(BRIGHTNESS_URI), eq(false),
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java
index d00e2c6..1f45792 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayEventDeliveryTest.java
@@ -33,6 +33,7 @@
 import android.content.Intent;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.VirtualDisplay;
+import android.os.BinderProxy;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -290,11 +291,15 @@
     }
 
     /**
-     * Return true if the freezer is enabled on this platform.
+     * Return true if the freezer is enabled on this platform and if freezer notifications are
+     * supported.  It is not enough to test that the freezer notification feature is enabled
+     * because some devices do not have the necessary kernel support.
      */
     private boolean isAppFreezerEnabled() {
         try {
-            return mActivityManager.getService().isAppFreezerEnabled();
+            return mActivityManager.getService().isAppFreezerEnabled()
+                    && android.os.Flags.binderFrozenStateChangeCallback()
+                    && BinderProxy.isFrozenStateChangeCallbackSupported();
         } catch (Exception e) {
             Log.e(TAG, "isAppFreezerEnabled() failed: " + e);
             return false;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index f96294ed..a9ad435 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -23,12 +23,14 @@
 import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS;
 import static android.Manifest.permission.MANAGE_DISPLAYS;
 import static android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE;
+import static android.hardware.display.DisplayManager.SWITCHING_TYPE_NONE;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_SYSTEM;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY;
 import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
@@ -123,6 +125,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.test.FakePermissionEnforcer;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -214,7 +217,8 @@
     private static final String PACKAGE_NAME = "com.android.frameworks.displayservicetests";
     private static final long STANDARD_DISPLAY_EVENTS =
             DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_ADDED
-            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_CHANGED
+            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_BASIC_CHANGED
+            | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REFRESH_RATE
             | DisplayManagerGlobal.INTERNAL_EVENT_FLAG_DISPLAY_REMOVED;
     private static final long STANDARD_AND_CONNECTION_DISPLAY_EVENTS =
             STANDARD_DISPLAY_EVENTS
@@ -222,7 +226,7 @@
 
     private static final String EVENT_DISPLAY_ADDED = "EVENT_DISPLAY_ADDED";
     private static final String EVENT_DISPLAY_REMOVED = "EVENT_DISPLAY_REMOVED";
-    private static final String EVENT_DISPLAY_CHANGED = "EVENT_DISPLAY_CHANGED";
+    private static final String EVENT_DISPLAY_BASIC_CHANGED = "EVENT_DISPLAY_BASIC_CHANGED";
     private static final String EVENT_DISPLAY_BRIGHTNESS_CHANGED =
             "EVENT_DISPLAY_BRIGHTNESS_CHANGED";
     private static final String EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED =
@@ -443,8 +447,6 @@
         when(mContext.getResources()).thenReturn(mResources);
         mUserManager = Mockito.spy(mContext.getSystemService(UserManager.class));
 
-        mPermissionEnforcer.grant(CONTROL_DISPLAY_BRIGHTNESS);
-        mPermissionEnforcer.grant(MODIFY_USER_PREFERRED_DISPLAY_MODE);
         doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
                 eq(PermissionEnforcer.class));
         doReturn(mPermissionEnforcer).when(mContext).getSystemService(
@@ -889,7 +891,6 @@
 
         FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
                 displayManager, bs, displayDevice);
-
         // Simulate DisplayDevice change
         DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
         displayDeviceInfo2.copyFrom(displayDeviceInfo);
@@ -900,7 +901,8 @@
 
         Handler handler = displayManager.getDisplayHandler();
         waitForIdleHandler(handler);
-        assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).containsExactly(EVENT_DISPLAY_BASIC_CHANGED,
+                EVENT_DISPLAY_REFRESH_RATE_CHANGED);
     }
 
     /**
@@ -2145,7 +2147,7 @@
                         new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
                 });
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_BASIC_CHANGED);
         callback.clear();
 
         updateFrameRateOverride(displayManager, displayDevice,
@@ -2154,7 +2156,7 @@
                         new DisplayEventReceiver.FrameRateOverride(1234, 30f),
                 });
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_BASIC_CHANGED);
 
         updateFrameRateOverride(displayManager, displayDevice,
                 new DisplayEventReceiver.FrameRateOverride[]{
@@ -2163,7 +2165,7 @@
                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
                 });
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_BASIC_CHANGED);
         callback.clear();
 
         updateFrameRateOverride(displayManager, displayDevice,
@@ -2172,7 +2174,7 @@
                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
                 });
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_BASIC_CHANGED);
         callback.clear();
 
         updateFrameRateOverride(displayManager, displayDevice,
@@ -2180,7 +2182,7 @@
                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
                 });
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_BASIC_CHANGED);
     }
 
     /**
@@ -2303,16 +2305,16 @@
 
         updateRenderFrameRate(displayManager, displayDevice, 30f);
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_REFRESH_RATE_CHANGED);
         callback.clear();
 
         updateRenderFrameRate(displayManager, displayDevice, 30f);
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_REFRESH_RATE_CHANGED);
 
         updateRenderFrameRate(displayManager, displayDevice, 20f);
         waitForIdleHandler(displayManager.getDisplayHandler());
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_REFRESH_RATE_CHANGED);
         callback.clear();
     }
 
@@ -2575,11 +2577,11 @@
                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 3));
         assertEquals(
-                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM),
-                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+                new HdrConversionMode(HDR_CONVERSION_SYSTEM),
+                new HdrConversionMode(HDR_CONVERSION_SYSTEM));
         assertNotEquals(
                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
-                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+                new HdrConversionMode(HDR_CONVERSION_SYSTEM));
     }
 
     @Test
@@ -2600,7 +2602,7 @@
                         + "HDR_CONVERSION_SYSTEM",
                 IllegalArgumentException.class,
                 () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
-                        HdrConversionMode.HDR_CONVERSION_SYSTEM,
+                        HDR_CONVERSION_SYSTEM,
                         Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
     }
 
@@ -2677,7 +2679,7 @@
         displayManager.setUserDisabledHdrTypesInternal(new int [0]);
         displayManager.setAreUserDisabledHdrTypesAllowedInternal(true);
         displayManager.setHdrConversionModeInternal(
-                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+                new HdrConversionMode(HDR_CONVERSION_SYSTEM));
 
         assertEquals(1, mAllowedHdrOutputTypes.length);
         assertTrue(Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION == mAllowedHdrOutputTypes[0]);
@@ -2731,7 +2733,7 @@
         assertTrue(logicalDisplay.getDisplayInfoLocked().isForceSdr);
 
         displayManager.setHdrConversionModeInternal(
-                new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
+                new HdrConversionMode(HDR_CONVERSION_SYSTEM));
         assertFalse(logicalDisplay.getDisplayInfoLocked().isForceSdr);
     }
 
@@ -3359,6 +3361,7 @@
 
     @Test
     public void testOnUserSwitching_UpdatesBrightness() {
+        mPermissionEnforcer.grant(CONTROL_DISPLAY_BRIGHTNESS);
         DisplayManagerService displayManager =
                 new DisplayManagerService(mContext, mShortMockedInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
@@ -3410,6 +3413,7 @@
 
     @Test
     public void testOnUserSwitching_brightnessForNewUserIsDefault() {
+        mPermissionEnforcer.grant(CONTROL_DISPLAY_BRIGHTNESS);
         DisplayManagerService displayManager =
                 new DisplayManagerService(mContext, mShortMockedInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
@@ -3438,7 +3442,8 @@
     }
 
     @Test
-    public void testResolutionChangeGetsBackedUp_FeatureFlagFalse() throws Exception {
+    public void testResolutionChangeGetsBackedUp_FeatureFlagFalse() {
+        mPermissionEnforcer.grant(MODIFY_USER_PREFERRED_DISPLAY_MODE);
         when(mMockFlags.isResolutionBackupRestoreEnabled()).thenReturn(false);
         DisplayManagerService displayManager =
                 new DisplayManagerService(mContext, mBasicInjector);
@@ -3464,6 +3469,7 @@
 
     @Test
     public void testBrightnessUpdates() {
+        mPermissionEnforcer.grant(CONTROL_DISPLAY_BRIGHTNESS);
         DisplayManagerService displayManager =
                 new DisplayManagerService(mContext, mShortMockedInjector);
         DisplayManagerInternal localService = displayManager.new LocalService();
@@ -3532,6 +3538,7 @@
 
     @Test
     public void testResolutionChangeGetsBackedUp() throws Exception {
+        mPermissionEnforcer.grant(MODIFY_USER_PREFERRED_DISPLAY_MODE);
         when(mMockFlags.isResolutionBackupRestoreEnabled()).thenReturn(true);
         DisplayManagerService displayManager =
                 new DisplayManagerService(mContext, mBasicInjector);
@@ -3888,7 +3895,7 @@
         observer.onChange(false, Settings.Secure.getUriFor(MIRROR_BUILT_IN_DISPLAY));
         waitForIdleHandler(handler);
 
-        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).doesNotContain(EVENT_DISPLAY_BASIC_CHANGED);
     }
 
     @Test
@@ -3910,16 +3917,310 @@
         waitForIdleHandler(handler);
 
         // Create a default display device
-        createFakeDisplayDevice(displayManager, new float[] {60f}, Display.TYPE_INTERNAL);
+        createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
         // Create a non-default display device
-        createFakeDisplayDevice(displayManager, new float[] {60f}, Display.TYPE_EXTERNAL);
+        createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
 
         Settings.Secure.putInt(mContext.getContentResolver(), MIRROR_BUILT_IN_DISPLAY, 1);
         final ContentObserver observer = displayManager.getSettingsObserver();
         observer.onChange(false, Settings.Secure.getUriFor(MIRROR_BUILT_IN_DISPLAY));
         waitForIdleHandler(handler);
 
-        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_CHANGED);
+        assertThat(callback.receivedEvents()).contains(EVENT_DISPLAY_BASIC_CHANGED);
+    }
+
+    @Test
+    public void startWifiDisplayScan_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, displayManagerBinderService::startWifiDisplayScan);
+    }
+
+    @Test
+    public void stopWifiDisplayScan_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, displayManagerBinderService::stopWifiDisplayScan);
+    }
+
+    @Test
+    public void connectWifiDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                () -> displayManagerBinderService.connectWifiDisplay("someAddress"));
+    }
+
+    @Test
+    public void renameWifiDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                () -> displayManagerBinderService.renameWifiDisplay("someAddress", "someAlias"));
+    }
+
+    @Test
+    public void forgetWifiDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                () -> displayManagerBinderService.forgetWifiDisplay("someAddress"));
+    }
+
+    @Test
+    public void pauseWifiDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, displayManagerBinderService::pauseWifiDisplay);
+    }
+
+    @Test
+    public void resumeWifiDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, displayManagerBinderService::resumeWifiDisplay);
+    }
+
+    @Test
+    public void setUserDisabledHdrTypes_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setUserDisabledHdrTypes(new int[0]));
+    }
+
+    @Test
+    public void setAreUserDisabledHdrTypesAllowed_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setAreUserDisabledHdrTypesAllowed(true));
+    }
+
+    @Test
+    public void requestColorMode_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService.requestColorMode(
+                Display.DEFAULT_DISPLAY, Display.COLOR_MODE_DEFAULT));
+    }
+
+    @Test
+    public void getBrightnessEvents_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.getBrightnessEvents("somePackage"));
+    }
+
+    @Test
+    public void getAmbientBrightnessStats_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                displayManagerBinderService::getAmbientBrightnessStats);
+    }
+
+    @Test
+    public void setBrightnessConfigurationForUser_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setBrightnessConfigurationForUser(
+                        new BrightnessConfiguration.Builder(/* lux= */ new float[]{0, 100},
+                                /* nits= */ new float[]{100, 200}).build(), UserHandle.USER_SYSTEM,
+                        "somePackage"));
+    }
+
+    @Test
+    public void setBrightnessConfigurationForDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setBrightnessConfigurationForDisplay(
+                        new BrightnessConfiguration.Builder(/* lux= */ new float[]{0, 100},
+                                /* nits= */ new float[]{100, 200}).build(), "uniqueId",
+                        UserHandle.USER_SYSTEM, "somePackage"));
+    }
+
+    @Test
+    public void getBrightnessConfigurationForDisplay_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.getBrightnessConfigurationForDisplay("uniqueId",
+                        UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void getDefaultBrightnessConfiguration_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                displayManagerBinderService::getDefaultBrightnessConfiguration);
+    }
+
+    @Test
+    public void getBrightnessInfo_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.getBrightnessInfo(Display.DEFAULT_DISPLAY));
+    }
+
+    @Test
+    public void setTemporaryBrightness_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setTemporaryBrightness(Display.DEFAULT_DISPLAY, 0.3f));
+    }
+
+    @Test
+    public void setBrightness_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setBrightness(Display.DEFAULT_DISPLAY, 0.3f));
+    }
+
+    @Test
+    public void getBrightness_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.getBrightness(Display.DEFAULT_DISPLAY));
+    }
+
+    @Test
+    public void setTemporaryAutoBrightnessAdjustment_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () ->
+                displayManagerBinderService.setTemporaryAutoBrightnessAdjustment(0.1f));
+    }
+
+    @Test
+    public void setUserPreferredDisplayMode_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .setUserPreferredDisplayMode(Display.DEFAULT_DISPLAY, new Display.Mode(
+                        /* width= */ 800, /* height= */ 600, /* refreshRate= */ 60)));
+    }
+
+    @Test
+    public void setHdrConversionMode_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .setHdrConversionMode(new HdrConversionMode(HDR_CONVERSION_SYSTEM)));
+    }
+
+    @Test
+    public void setShouldAlwaysRespectAppRequestedMode_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .setShouldAlwaysRespectAppRequestedMode(true));
+    }
+
+    @Test
+    public void shouldAlwaysRespectAppRequestedMode_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class,
+                displayManagerBinderService::shouldAlwaysRespectAppRequestedMode);
+    }
+
+    @Test
+    public void setRefreshRateSwitchingType_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .setRefreshRateSwitchingType(SWITCHING_TYPE_NONE));
+    }
+
+    @Test
+    public void requestDisplayModes_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .requestDisplayModes(new Binder(), Display.DEFAULT_DISPLAY, new int[0]));
+    }
+
+    @Test
+    public void getDozeBrightnessSensorValueToBrightness_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .getDozeBrightnessSensorValueToBrightness(Display.DEFAULT_DISPLAY));
+    }
+
+    @Test
+    public void getDefaultDozeBrightness_withoutPermission_shouldThrowException() {
+        DisplayManagerService displayManager =
+                new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerService.BinderService displayManagerBinderService =
+                displayManager.new BinderService();
+        assertThrows(SecurityException.class, () -> displayManagerBinderService
+                .getDefaultDozeBrightness(Display.DEFAULT_DISPLAY));
     }
 
     private void initDisplayPowerController(DisplayManagerInternal localService) {
@@ -4389,8 +4690,8 @@
                     return EVENT_DISPLAY_ADDED;
                 case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED:
                     return EVENT_DISPLAY_REMOVED;
-                case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED:
-                    return EVENT_DISPLAY_CHANGED;
+                case DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED:
+                    return EVENT_DISPLAY_BASIC_CHANGED;
                 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED:
                     return EVENT_DISPLAY_BRIGHTNESS_CHANGED;
                 case DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED:
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index a4dfecb..7f12e9c 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1401,33 +1401,9 @@
     }
 
     @Test
-    public void testRampRateForHdrContent_HdrClamperOff() {
-        float hdrBrightness = 0.8f;
-        float clampedBrightness = 0.6f;
-        float transitionRate = 1.5f;
-
-        DisplayPowerRequest dpr = new DisplayPowerRequest();
-        when(mHolder.displayPowerState.getColorFadeLevel()).thenReturn(1.0f);
-        when(mHolder.displayPowerState.getScreenBrightness()).thenReturn(.2f);
-        when(mHolder.displayPowerState.getSdrScreenBrightness()).thenReturn(.1f);
-        when(mHolder.hbmController.getHighBrightnessMode()).thenReturn(
-                BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR);
-        when(mHolder.hbmController.getHdrBrightnessValue()).thenReturn(hdrBrightness);
-        when(mHolder.hdrClamper.getMaxBrightness()).thenReturn(clampedBrightness);
-        when(mHolder.hdrClamper.getTransitionRate()).thenReturn(transitionRate);
-
-        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
-        advanceTime(1); // Run updatePowerState
-
-        verify(mHolder.animator, atLeastOnce()).animateTo(eq(hdrBrightness), anyFloat(),
-                eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE), eq(false));
-    }
-
-    @Test
     public void testRampRateForHdrContent_HdrClamperOn() {
         float clampedBrightness = 0.6f;
         float transitionRate = 1.5f;
-        when(mDisplayManagerFlagsMock.isHdrClamperEnabled()).thenReturn(true);
         mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ true);
 
         DisplayPowerRequest dpr = new DisplayPowerRequest();
@@ -2631,6 +2607,8 @@
         BrightnessClamperController clamperController = mock(BrightnessClamperController.class);
 
         when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX);
+        when(hdrClamper.clamp(anyFloat())).thenAnswer(
+                invocation -> invocation.getArgument(0));
         when(clamperController.clamp(any(), any(), anyFloat(), anyBoolean(),
                 anyInt())).thenAnswer(
                 invocation -> DisplayBrightnessState.Builder.from(mDisplayBrightnessState)
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
index 5d42713..c65024f8 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt
@@ -26,6 +26,7 @@
 import org.mockito.ArgumentMatchers.anyFloat
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.never
 import org.mockito.kotlin.verify
@@ -43,7 +44,7 @@
 
     @Before
     fun setUp() {
-        displayInfo.displayId = 2
+        displayInfo.displayId = Display.DEFAULT_DISPLAY
         displayInfo.logicalWidth = 300
         displayInfo.logicalHeight = 200
         displayInfo.logicalDensityDpi = 100
@@ -90,6 +91,44 @@
     }
 
     @Test
+    fun updateDisplay() {
+        whenever(mockTopology.updateDisplay(eq(Display.DEFAULT_DISPLAY), anyFloat(), anyFloat()))
+            .thenReturn(true)
+
+        coordinator.onDisplayChanged(displayInfo)
+
+        verify(mockTopologyChangedCallback).invoke(mockTopologyCopy)
+    }
+
+    @Test
+    fun updateDisplay_notChanged() {
+        whenever(mockTopology.updateDisplay(eq(Display.DEFAULT_DISPLAY), anyFloat(), anyFloat()))
+            .thenReturn(false)
+
+        coordinator.onDisplayChanged(displayInfo)
+
+        verify(mockTopologyChangedCallback, never()).invoke(any())
+    }
+
+    @Test
+    fun removeDisplay() {
+        whenever(mockTopology.removeDisplay(Display.DEFAULT_DISPLAY)).thenReturn(true)
+
+        coordinator.onDisplayRemoved(Display.DEFAULT_DISPLAY)
+
+        verify(mockTopologyChangedCallback).invoke(mockTopologyCopy)
+    }
+
+    @Test
+    fun removeDisplay_notChanged() {
+        whenever(mockTopology.removeDisplay(Display.DEFAULT_DISPLAY)).thenReturn(false)
+
+        coordinator.onDisplayRemoved(Display.DEFAULT_DISPLAY)
+
+        verify(mockTopologyChangedCallback, never()).invoke(any())
+    }
+
+    @Test
     fun getTopology_copy() {
         assertThat(coordinator.topology).isEqualTo(mockTopologyCopy)
     }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index cde87b9..255d236 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -720,6 +720,25 @@
                         .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LOW_REQUESTED_BRIGHTNESS));
     }
 
+    @Test
+    public void testDoesNotAcceptExternalHdrLayerUpdates_hdrBoostEnabled() {
+        final HighBrightnessModeController hbmc = createDefaultHbm();
+        assertFalse(hbmc.mIsHdrLayerPresent);
+
+        hbmc.onHdrBoostApplied(true);
+        assertFalse(hbmc.mIsHdrLayerPresent);
+    }
+
+    @Test
+    public void testAcceptsExternalHdrLayerUpdates_hdrBoostDisabled() {
+        final HighBrightnessModeController hbmc = createDefaultHbm();
+        hbmc.disableHdrBoost();
+        assertFalse(hbmc.mIsHdrLayerPresent);
+
+        hbmc.onHdrBoostApplied(true);
+        assertTrue(hbmc.mIsHdrLayerPresent);
+    }
+
     private void assertState(HighBrightnessModeController hbmc,
             float brightnessMin, float brightnessMax, int hbmMode) {
         assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index ad30f22..0dbb6ba 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -36,9 +36,9 @@
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CONNECTED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DISCONNECTED;
-import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED;
 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_STATE_CHANGED;
+import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED;
 import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
 import static com.android.server.display.layout.Layout.Display.POSITION_UNKNOWN;
 import static com.android.server.utils.FoldSettingProvider.SETTING_VALUE_SELECTIVE_STAY_AWAKE;
@@ -1170,17 +1170,19 @@
 
     @Test
     public void updateAndGetMaskForDisplayPropertyChanges_getsPropertyChangedFlags() {
-        // Change the display state
+        // Change the refresh rate override
         DisplayInfo newDisplayInfo = new DisplayInfo();
+        newDisplayInfo.refreshRateOverride = 30;
+        assertEquals(LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED,
+                mLogicalDisplayMapper.updateAndGetMaskForDisplayPropertyChanges(newDisplayInfo));
+
+        // Change the display state
+        when(mFlagsMock.isDisplayListenerPerformanceImprovementsEnabled()).thenReturn(true);
+        newDisplayInfo = new DisplayInfo();
         newDisplayInfo.state = STATE_OFF;
         assertEquals(LOGICAL_DISPLAY_EVENT_STATE_CHANGED,
                 mLogicalDisplayMapper.updateAndGetMaskForDisplayPropertyChanges(newDisplayInfo));
 
-        // Change the refresh rate override
-        newDisplayInfo = new DisplayInfo();
-        newDisplayInfo.refreshRateOverride = 30;
-        assertEquals(LOGICAL_DISPLAY_EVENT_REFRESH_RATE_CHANGED,
-                mLogicalDisplayMapper.updateAndGetMaskForDisplayPropertyChanges(newDisplayInfo));
 
         // Change multiple properties
         newDisplayInfo = new DisplayInfo();
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 4e0bab8..f154dbc 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -1225,8 +1225,8 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         setBrightness(10, 10, displayListener);
@@ -1256,8 +1256,8 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         setBrightness(10, 10, displayListener);
@@ -1291,8 +1291,8 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         setBrightness(10, 10, displayListener);
@@ -1325,8 +1325,8 @@
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
@@ -1404,8 +1404,8 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
@@ -1464,8 +1464,8 @@
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         ArgumentCaptor<SensorEventListener> listenerCaptor =
@@ -1630,8 +1630,8 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         // Get the sensor listener so that we can give it new light sensor events
@@ -1730,8 +1730,8 @@
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_CHANGED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener displayListener = displayListenerCaptor.getValue();
 
         // Get the sensor listener so that we can give it new light sensor events
@@ -2814,9 +2814,9 @@
                 ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector, times(2)).registerDisplayListener(DisplayCaptor.capture(),
                 any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_ADDED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
-                        | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_ADDED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_CHANGED
+                        | DisplayManager.EVENT_TYPE_DISPLAY_REMOVED));
         DisplayListener displayListener = DisplayCaptor.getAllValues().get(0);
 
         // Verify that there is no proximity vote initially
@@ -2877,8 +2877,8 @@
         ArgumentCaptor<DisplayListener> captor =
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         // Specify Limitation
@@ -3000,8 +3000,8 @@
         ArgumentCaptor<DisplayListener> captor =
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         final int initialRefreshRate = 60;
@@ -3075,8 +3075,8 @@
         ArgumentCaptor<DisplayListener> captor =
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         // Specify Limitation for different display
@@ -3115,8 +3115,8 @@
         ArgumentCaptor<DisplayListener> captor =
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         // Specify Limitation
@@ -3200,8 +3200,8 @@
 
         ArgumentCaptor<DisplayListener> captor = ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         // Specify Sunlight limitations
@@ -3239,8 +3239,8 @@
         ArgumentCaptor<DisplayListener> captor =
                   ArgumentCaptor.forClass(DisplayListener.class);
         verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
-                eq(DisplayManager.EVENT_FLAG_DISPLAY_REMOVED),
-                eq(DisplayManager.PRIVATE_EVENT_FLAG_DISPLAY_BRIGHTNESS));
+                eq(DisplayManager.EVENT_TYPE_DISPLAY_REMOVED),
+                eq(DisplayManager.PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS));
         DisplayListener listener = captor.getValue();
 
         // Specify Limitation for different display
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index 94d4b95..03bd73c 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -24,6 +24,7 @@
         ":lib_freezer_native",
         ":lib_oomConnection_native",
         ":lib_lazilyRegisteredServices_native",
+        ":lib_phantomProcessList_native",
         "onload.cpp",
     ],
 
diff --git a/services/tests/mockingservicestests/jni/onload.cpp b/services/tests/mockingservicestests/jni/onload.cpp
index 9b4c817..30fa7de 100644
--- a/services/tests/mockingservicestests/jni/onload.cpp
+++ b/services/tests/mockingservicestests/jni/onload.cpp
@@ -28,6 +28,7 @@
 int register_android_server_am_Freezer(JNIEnv* env);
 int register_android_server_am_OomConnection(JNIEnv* env);
 int register_android_server_utils_LazyJniRegistrar(JNIEnv* env);
+int register_android_server_am_PhantomProcessList(JNIEnv* env);
 };
 
 using namespace android;
@@ -46,5 +47,6 @@
     register_android_server_am_Freezer(env);
     register_android_server_am_OomConnection(env);
     register_android_server_utils_LazyJniRegistrar(env);
+    register_android_server_am_PhantomProcessList(env);
     return JNI_VERSION_1_4;
 }
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 4b2e850..bd15bd0 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -70,17 +70,23 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SessionCreationConfig;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.Log;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.power.hint.HintManagerService.AppHintSession;
 import com.android.server.power.hint.HintManagerService.Injector;
 import com.android.server.power.hint.HintManagerService.NativeWrapper;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -89,6 +95,10 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -106,6 +116,7 @@
  */
 public class HintManagerServiceTest {
     private static final String TAG = "HintManagerServiceTest";
+    private List<File> mFilesCreated = new ArrayList<>();
 
     private static WorkDuration makeWorkDuration(
             long timestamp, long duration, long workPeriodStartTime,
@@ -160,6 +171,8 @@
     @Rule
     public final CheckFlagsRule mCheckFlagsRule =
             DeviceFlagsValueProvider.createCheckFlagsRule();
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     private HintManagerService mService;
     private ChannelConfig mConfig;
@@ -185,9 +198,9 @@
         mSupportInfo.sessionTags = -1;
         mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo();
         mSupportInfo.headroom.isCpuSupported = true;
-        mSupportInfo.headroom.cpuMinIntervalMillis = 2000;
+        mSupportInfo.headroom.cpuMinIntervalMillis = 1000;
         mSupportInfo.headroom.isGpuSupported = true;
-        mSupportInfo.headroom.gpuMinIntervalMillis = 2000;
+        mSupportInfo.headroom.gpuMinIntervalMillis = 1000;
         mSupportInfo.compositionData = new SupportInfo.CompositionDataSupportInfo();
         return mSupportInfo;
     }
@@ -236,6 +249,13 @@
         LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock);
     }
 
+    @After
+    public void tearDown() {
+        for (File file : mFilesCreated) {
+            file.delete();
+        }
+    }
+
     /**
      * Mocks the creation calls, but without support for new createHintSessionWithConfig method
      */
@@ -371,19 +391,19 @@
                 makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
 
         IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, new SessionConfig());
+                SessionTag.OTHER, creationConfig, new SessionConfig()).session;
         assertNotNull(a);
 
         creationConfig.tids = SESSION_TIDS_B;
         creationConfig.targetWorkDurationNanos = DOUBLED_TARGET_DURATION;
         IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, new SessionConfig());
+                SessionTag.OTHER, creationConfig, new SessionConfig()).session;
         assertNotEquals(a, b);
 
         creationConfig.tids = SESSION_TIDS_C;
         creationConfig.targetWorkDurationNanos = 0L;
         IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, new SessionConfig());
+                SessionTag.OTHER, creationConfig, new SessionConfig()).session;
         assertNotNull(c);
         verify(mNativeWrapperMock, times(3)).halCreateHintSession(anyInt(), anyInt(),
                 any(int[].class), anyLong());
@@ -398,7 +418,7 @@
 
         SessionConfig config = new SessionConfig();
         IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, config);
+                SessionTag.OTHER, creationConfig, config).session;
         assertNotNull(a);
         assertEquals(SESSION_IDS[0], config.id);
 
@@ -406,7 +426,7 @@
         creationConfig.tids = SESSION_TIDS_B;
         creationConfig.targetWorkDurationNanos = DOUBLED_TARGET_DURATION;
         IHintSession b = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.APP, creationConfig, config2);
+                SessionTag.APP, creationConfig, config2).session;
         assertNotEquals(a, b);
         assertEquals(SESSION_IDS[1], config2.id);
 
@@ -414,7 +434,7 @@
         creationConfig.tids = SESSION_TIDS_C;
         creationConfig.targetWorkDurationNanos = 0L;
         IHintSession c = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.GAME, creationConfig, config3);
+                SessionTag.GAME, creationConfig, config3).session;
         assertNotNull(c);
         assertEquals(SESSION_IDS[2], config3.id);
         verify(mNativeWrapperMock, times(3)).halCreateHintSessionWithConfig(anyInt(), anyInt(),
@@ -445,16 +465,14 @@
 
         SessionConfig config = new SessionConfig();
         IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, config);
+                SessionTag.OTHER, creationConfig, config).session;
         assertNotNull(a);
         assertEquals(sessionId1, config.id);
 
         creationConfig.tids = createThreads(1, stopLatch1);
 
-        assertThrows(IllegalArgumentException.class, () -> {
-            service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                    SessionTag.OTHER, creationConfig, config);
-        });
+        assertEquals(service.getBinderServiceInstance().createHintSessionWithConfig(token,
+                    SessionTag.OTHER, creationConfig, config).pipelineThreadLimitExceeded, true);
     }
 
     @Test
@@ -466,7 +484,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         // Set session to background and calling updateHintAllowedByProcState() would invoke
         // pause();
@@ -506,7 +524,7 @@
                 makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
 
         IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, new SessionConfig());
+                SessionTag.OTHER, creationConfig, new SessionConfig()).session;
 
         a.close();
         verify(mNativeWrapperMock, times(1)).halCloseHintSession(anyLong());
@@ -520,16 +538,12 @@
                 makeSessionCreationConfig(SESSION_TIDS_A, DEFAULT_TARGET_DURATION);
 
         IHintSession a = service.getBinderServiceInstance().createHintSessionWithConfig(token,
-                SessionTag.OTHER, creationConfig, new SessionConfig());
+                SessionTag.OTHER, creationConfig, new SessionConfig()).session;
 
         assertThrows(IllegalArgumentException.class, () -> {
             a.updateTargetWorkDuration(-1L);
         });
 
-        assertThrows(IllegalArgumentException.class, () -> {
-            a.updateTargetWorkDuration(0L);
-        });
-
         a.updateTargetWorkDuration(100L);
         verify(mNativeWrapperMock, times(1)).halUpdateTargetWorkDuration(anyLong(), eq(100L));
     }
@@ -543,7 +557,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         a.updateTargetWorkDuration(100L);
         a.reportActualWorkDuration(DURATIONS_THREE, TIMESTAMPS_THREE);
@@ -588,7 +602,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         a.sendHint(PerformanceHintManager.Session.CPU_LOAD_RESET);
         verify(mNativeWrapperMock, times(1)).halSendHint(anyLong(),
@@ -617,7 +631,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         service.mUidObserver.onUidStateChanged(
                 a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
@@ -641,7 +655,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         service.mUidObserver.onUidStateChanged(
                 a.mUid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0);
@@ -657,7 +671,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         a.updateTargetWorkDuration(100L);
 
@@ -697,7 +711,7 @@
                 makeSessionCreationConfig(tids1, DEFAULT_TARGET_DURATION);
         AppHintSession session1 = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
         assertNotNull(session1);
 
         // trigger UID state change by making the process foreground->background, but because the
@@ -734,7 +748,7 @@
                 makeSessionCreationConfig(tids1, DEFAULT_TARGET_DURATION);
         AppHintSession session1 = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
         assertNotNull(session1);
 
         // let all session 1 threads to exit and the cleanup should force pause the session 1
@@ -845,7 +859,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         a.setMode(0, true);
         verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(),
@@ -865,7 +879,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         // Set session to background, then the duration would not be updated.
         service.mUidObserver.onUidStateChanged(
@@ -886,7 +900,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         assertThrows(IllegalArgumentException.class, () -> {
             a.setMode(-1, true);
@@ -903,7 +917,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
         assertNotNull(a);
         verify(mNativeWrapperMock, times(1)).halSetMode(anyLong(),
                 eq(0), eq(true));
@@ -1104,7 +1118,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
         // we will start some threads and get their valid TIDs to update
         int threadCount = 3;
         // the list of TIDs
@@ -1174,7 +1188,7 @@
 
         AppHintSession a = (AppHintSession) service.getBinderServiceInstance()
                 .createHintSessionWithConfig(token, SessionTag.OTHER,
-                        creationConfig, new SessionConfig());
+                        creationConfig, new SessionConfig()).session;
 
         a.updateTargetWorkDuration(100L);
         a.reportActualWorkDuration2(WORK_DURATIONS_FIVE);
@@ -1320,8 +1334,61 @@
         });
     }
 
+    @Test
+    public void testCpuHeadroomCpuProcStatPath() throws Exception {
+        File dir = InstrumentationRegistry.getTargetContext().getFilesDir();
+        dir.mkdir();
+        String procStatFileStr = "mock_proc_stat";
+        File file = new File(dir, procStatFileStr);
+        mFilesCreated.add(file);
+        try (FileOutputStream output = new FileOutputStream(file)) {
+            output.write("cpu  2000 3000 4000 0 0 0 0 0 0 0".getBytes());
+        }
+        HintManagerService service = createService();
+        service.setProcStatPathOverride(file.getPath());
+
+        CpuHeadroomParamsInternal params1 = new CpuHeadroomParamsInternal();
+        CpuHeadroomParams halParams1 = new CpuHeadroomParams();
+        halParams1.calculationType = CpuHeadroomParams.CalculationType.MIN;
+        halParams1.tids = new int[]{Process.myPid()};
+
+        float headroom1 = 0.1f;
+        CpuHeadroomResult halRet1 = CpuHeadroomResult.globalHeadroom(headroom1);
+        when(mIPowerMock.getCpuHeadroom(eq(halParams1))).thenReturn(halRet1);
+        clearInvocations(mIPowerMock);
+        assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
+        verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams1));
+        // expire the cache but cpu proc hasn't changed so we expect no value return
+        Thread.sleep(1100);
+        clearInvocations(mIPowerMock);
+        assertEquals(null, service.getBinderServiceInstance().getCpuHeadroom(params1));
+        verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams1));
+
+        // update user jiffies with 500 equivalent jiffies, which is not sufficient cpu time
+        Thread.sleep(1100);
+        try (FileOutputStream output = new FileOutputStream(file)) {
+            output.write(("cpu  " + (2000 + (int) (500 / service.mJiffyMillis))
+                    + " 3000 4000 0 0 0 0 0 0 0").getBytes());
+        }
+        clearInvocations(mIPowerMock);
+        assertEquals(null, service.getBinderServiceInstance().getCpuHeadroom(params1));
+        verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams1));
+
+        // update nice jiffies with 600 equivalent jiffies, now it exceeds 1000ms requirement
+        Thread.sleep(1100);
+        try (FileOutputStream output = new FileOutputStream(file)) {
+            output.write(("cpu  " + (2000 + (int) (500 / service.mJiffyMillis))
+                    + " " + +(3000 + (int) (600 / service.mJiffyMillis))
+                    + " 4000 0 0 0 0 0 0 0").getBytes());
+        }
+        clearInvocations(mIPowerMock);
+        assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
+        verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams1));
+    }
+
 
     @Test
+    @EnableFlags({Flags.FLAG_CPU_HEADROOM_AFFINITY_CHECK})
     public void testCpuHeadroomCache() throws Exception {
         CpuHeadroomParamsInternal params1 = new CpuHeadroomParamsInternal();
         CpuHeadroomParams halParams1 = new CpuHeadroomParams();
@@ -1335,11 +1402,14 @@
         halParams2.calculationType = CpuHeadroomParams.CalculationType.MIN;
         halParams2.tids = new int[]{};
 
+        CountDownLatch latch = new CountDownLatch(2);
+        int[] tids = createThreads(2, latch);
         CpuHeadroomParamsInternal params3 = new CpuHeadroomParamsInternal();
+        params3.tids = tids;
         params3.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
         CpuHeadroomParams halParams3 = new CpuHeadroomParams();
+        halParams3.tids = tids;
         halParams3.calculationType = CpuHeadroomParams.CalculationType.AVERAGE;
-        halParams3.tids = new int[]{Process.myPid()};
 
         // this params should not be cached as the window is not default
         CpuHeadroomParamsInternal params4 = new CpuHeadroomParamsInternal();
@@ -1386,8 +1456,8 @@
         verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams3));
         verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
 
-        // after 1 more second it should be served with cache still
-        Thread.sleep(1000);
+        // after 500ms more it should be served with cache
+        Thread.sleep(500);
         clearInvocations(mIPowerMock);
         assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
         assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
@@ -1399,8 +1469,8 @@
         verify(mIPowerMock, times(0)).getCpuHeadroom(eq(halParams3));
         verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
 
-        // after 2+ seconds it should be served from HAL as it exceeds 2000 millis interval
-        Thread.sleep(1100);
+        // after 1+ seconds it should be served from HAL as it exceeds 1000 millis interval
+        Thread.sleep(600);
         clearInvocations(mIPowerMock);
         assertEquals(halRet1, service.getBinderServiceInstance().getCpuHeadroom(params1));
         assertEquals(halRet2, service.getBinderServiceInstance().getCpuHeadroom(params2));
@@ -1411,6 +1481,65 @@
         verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams2));
         verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams3));
         verify(mIPowerMock, times(1)).getCpuHeadroom(eq(halParams4));
+        latch.countDown();
+    }
+
+    @Test
+    @EnableFlags({Flags.FLAG_CPU_HEADROOM_AFFINITY_CHECK})
+    public void testGetCpuHeadroomDifferentAffinity_flagOn() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
+        int[] tids = createThreads(2, latch);
+        CpuHeadroomParamsInternal params = new CpuHeadroomParamsInternal();
+        params.tids = tids;
+        CpuHeadroomParams halParams = new CpuHeadroomParams();
+        halParams.tids = tids;
+        float headroom = 0.1f;
+        CpuHeadroomResult halRet = CpuHeadroomResult.globalHeadroom(headroom);
+        String ret1 = runAndWaitForCommand("taskset -p 1 " + tids[0]);
+        String ret2 = runAndWaitForCommand("taskset -p 3 " + tids[1]);
+
+        HintManagerService service = createService();
+        clearInvocations(mIPowerMock);
+        when(mIPowerMock.getCpuHeadroom(eq(halParams))).thenReturn(halRet);
+        assertThrows("taskset cmd return: " + ret1 + "\n" + ret2, IllegalStateException.class,
+                () -> service.getBinderServiceInstance().getCpuHeadroom(params));
+        verify(mIPowerMock, times(0)).getCpuHeadroom(any());
+    }
+
+    @Test
+    @DisableFlags({Flags.FLAG_CPU_HEADROOM_AFFINITY_CHECK})
+    public void testGetCpuHeadroomDifferentAffinity_flagOff() throws Exception {
+        CountDownLatch latch = new CountDownLatch(2);
+        int[] tids = createThreads(2, latch);
+        CpuHeadroomParamsInternal params = new CpuHeadroomParamsInternal();
+        params.tids = tids;
+        CpuHeadroomParams halParams = new CpuHeadroomParams();
+        halParams.tids = tids;
+        float headroom = 0.1f;
+        CpuHeadroomResult halRet = CpuHeadroomResult.globalHeadroom(headroom);
+        String ret1 = runAndWaitForCommand("taskset -p 1 " + tids[0]);
+        String ret2 = runAndWaitForCommand("taskset -p 3 " + tids[1]);
+
+        HintManagerService service = createService();
+        clearInvocations(mIPowerMock);
+        when(mIPowerMock.getCpuHeadroom(eq(halParams))).thenReturn(halRet);
+        assertEquals("taskset cmd return: " + ret1 + "\n" + ret2, halRet,
+                service.getBinderServiceInstance().getCpuHeadroom(params));
+        verify(mIPowerMock, times(1)).getCpuHeadroom(any());
+    }
+
+    private String runAndWaitForCommand(String command) throws Exception {
+        java.lang.Process process = Runtime.getRuntime().exec(command);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+        String line;
+        StringBuilder res = new StringBuilder();
+        while ((line = reader.readLine()) != null) {
+            res.append(line);
+        }
+        process.waitFor();
+        // somehow the exit code can be 1 for the taskset command though it exits successfully,
+        // thus we just return the output
+        return res.toString();
     }
 
     @Test
@@ -1449,8 +1578,8 @@
         verify(mIPowerMock, times(0)).getGpuHeadroom(eq(halParams1));
         verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
 
-        // after 1 more second it should be served with cache still
-        Thread.sleep(1000);
+        // after 500ms it should be served with cache
+        Thread.sleep(500);
         clearInvocations(mIPowerMock);
         assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
         assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
@@ -1458,8 +1587,8 @@
         verify(mIPowerMock, times(0)).getGpuHeadroom(eq(halParams1));
         verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2));
 
-        // after 2+ seconds it should be served from HAL as it exceeds 2000 millis interval
-        Thread.sleep(1100);
+        // after 1+ seconds it should be served from HAL as it exceeds 1000 millis interval
+        Thread.sleep(600);
         clearInvocations(mIPowerMock);
         assertEquals(halRet1, service.getBinderServiceInstance().getGpuHeadroom(params1));
         assertEquals(halRet2, service.getBinderServiceInstance().getGpuHeadroom(params2));
diff --git a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
index 96741e0..83a390d 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/NotifierTest.java
@@ -16,11 +16,14 @@
 
 package com.android.server.power;
 
+import static android.os.PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON;
+import static android.os.PowerManager.SCREEN_TIMEOUT_ACTIVE;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
@@ -29,6 +32,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -48,7 +52,9 @@
 import android.os.BatteryStats;
 import android.os.BatteryStatsInternal;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.IWakeLockCallback;
+import android.os.IScreenTimeoutPolicyListener;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -83,6 +89,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.concurrent.Executor;
@@ -889,6 +896,227 @@
                 "my.package.name", false, null, null);
     }
 
+    @Test
+    public void getWakelockMonitorTypeForLogging_evaluatesWakelockLevel() {
+        createNotifier();
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.SCREEN_DIM_WAKE_LOCK),
+                PowerManager.FULL_WAKE_LOCK);
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
+                PowerManager.SCREEN_BRIGHT_WAKE_LOCK), PowerManager.FULL_WAKE_LOCK);
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.DRAW_WAKE_LOCK),
+                PowerManager.DRAW_WAKE_LOCK);
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(PowerManager.PARTIAL_WAKE_LOCK),
+                PowerManager.PARTIAL_WAKE_LOCK);
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
+                        PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK),
+                PowerManager.PARTIAL_WAKE_LOCK);
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
+                        PowerManager.DOZE_WAKE_LOCK), -1);
+
+        when(mResourcesSpy.getBoolean(
+                com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity))
+                .thenReturn(true);
+
+        createNotifier();
+        assertEquals(mNotifier.getWakelockMonitorTypeForLogging(
+                        PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK), -1);
+    }
+
+    @Test
+    public void testScreenTimeoutListener_reportsScreenTimeoutPolicyChange() throws Exception {
+        createNotifier();
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
+                /* hasScreenWakeLock= */ SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+
+        // Verify that the event is sent asynchronously on a handler
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+        mTestLooper.dispatchAll();
+        verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+    }
+
+    @Test
+    public void testScreenTimeoutListener_addAndRemoveListener_doesNotInvokeListener()
+            throws Exception {
+        createNotifier();
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+        mNotifier.removeScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY, listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        // Callback should not be fired as listener is removed
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+    }
+
+    @Test
+    public void testScreenTimeoutListener_addAndClearListeners_doesNotInvokeListener()
+            throws Exception {
+        createNotifier();
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+        mNotifier.clearScreenTimeoutPolicyListeners(Display.DEFAULT_DISPLAY);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        // Callback should not be fired as listener is removed
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+    }
+
+    @Test
+    public void testScreenTimeoutListener_subscribedToAnotherDisplay_listenerNotFired()
+            throws Exception {
+        createNotifier();
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(/* displayGroupId= */ 123,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        // Callback should not be fired as we subscribed only to the DEFAULT_DISPLAY
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+    }
+
+    @Test
+    public void testScreenTimeoutListener_listenerDied_listenerNotFired()
+            throws Exception {
+        createNotifier();
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+
+        ArgumentCaptor<IBinder.DeathRecipient> captor =
+                ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
+        verify(listenerBinder).linkToDeath(captor.capture(), anyInt());
+        mTestLooper.dispatchAll();
+        captor.getValue().binderDied();
+        clearInvocations(listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        // Callback should not be fired as binder died
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+    }
+
+    @Test
+    public void testScreenTimeoutListener_listenerThrowsException_listenerNotFiredSecondTime()
+            throws Exception {
+        createNotifier();
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        doThrow(RuntimeException.class).when(listener).onScreenTimeoutPolicyChanged(anyInt());
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        // Callback should not be fired as it has thrown an exception once
+        verify(listener, never()).onScreenTimeoutPolicyChanged(anyInt());
+    }
+
+    @Test
+    public void testScreenTimeoutListener_nonDefaultDisplay_stillReportsPolicyCorrectly()
+            throws Exception {
+        createNotifier();
+        final int otherDisplayId = 123;
+        final int otherDisplayGroupId = 123_00;
+        when(mDisplayManagerInternal.getGroupIdForDisplay(otherDisplayId)).thenReturn(
+                otherDisplayGroupId);
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+        mNotifier.addScreenTimeoutPolicyListener(otherDisplayId,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+        clearInvocations(listener);
+
+        mNotifier.notifyScreenTimeoutPolicyChanges(otherDisplayGroupId,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+        mTestLooper.dispatchAll();
+
+        verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+    }
+
+    @Test
+    public void testScreenTimeoutListener_timeoutPolicyTimeout_reportsTimeoutOnSubscription()
+            throws Exception {
+        createNotifier();
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        mTestLooper.dispatchAll();
+
+        verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_ACTIVE);
+    }
+
+    @Test
+    public void testScreenTimeoutListener_policyHeld_reportsHeldOnSubscription()
+            throws Exception {
+        createNotifier();
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        final IBinder listenerBinder = Mockito.mock(IBinder.class);
+        when(listener.asBinder()).thenReturn(listenerBinder);
+
+        mNotifier.addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON, listener);
+        mTestLooper.dispatchAll();
+
+        verify(listener).onScreenTimeoutPolicyChanged(SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+    }
+
     private final PowerManagerService.Injector mInjector = new PowerManagerService.Injector() {
         @Override
         Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
index 376091e..3cb2745 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -20,6 +20,8 @@
 import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
 import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING;
+import static android.os.PowerManager.SCREEN_TIMEOUT_KEEP_DISPLAY_ON;
+import static android.os.PowerManager.SCREEN_TIMEOUT_ACTIVE;
 import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON;
 import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
 import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -69,6 +71,7 @@
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
 import android.hardware.display.AmbientDisplayConfiguration;
+import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.power.Boost;
 import android.hardware.power.Mode;
@@ -79,6 +82,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IWakeLockCallback;
+import android.os.IScreenTimeoutPolicyListener;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.PowerManagerInternal;
@@ -132,6 +136,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -166,6 +171,7 @@
     @Mock private BatterySaverStateMachine mBatterySaverStateMachineMock;
     @Mock private LightsManager mLightsManagerMock;
     @Mock private DisplayManagerInternal mDisplayManagerInternalMock;
+    @Mock private DisplayManager mDisplayManagerMock;
     @Mock private BatteryManagerInternal mBatteryManagerInternalMock;
     @Mock private ActivityManagerInternal mActivityManagerInternalMock;
     @Mock private AttentionManagerInternal mAttentionManagerInternalMock;
@@ -185,6 +191,8 @@
     @Mock private DeviceStateManager mDeviceStateManagerMock;
     @Mock private DeviceConfigParameterProvider mDeviceParameterProvider;
 
+    @Captor private ArgumentCaptor<DisplayManager.DisplayListener> mDisplayListenerArgumentCaptor;
+
     @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule();
 
     @Rule public SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -254,6 +262,7 @@
         mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mResourcesSpy = spy(mContextSpy.getResources());
         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+        when(mContextSpy.getSystemService(DisplayManager.class)).thenReturn(mDisplayManagerMock);
         setBatterySaverSupported();
 
         MockContentResolver cr = new MockContentResolver(mContextSpy);
@@ -2947,15 +2956,19 @@
         assertThat(mService.getPowerGroupSize()).isEqualTo(4);
     }
 
-    private WakeLock acquireWakeLock(String tag, int flags) {
+    private WakeLock acquireWakeLock(String tag, int flags, int displayId) {
         IBinder token = new Binder();
         String packageName = "pkg.name";
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
-                null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY,
+                null /* workSource */, null /* historyTag */, displayId,
                 null /* callback */);
         return mService.findWakeLockLocked(token);
     }
 
+    private WakeLock acquireWakeLock(String tag, int flags) {
+        return acquireWakeLock(tag, flags, Display.INVALID_DISPLAY);
+    }
+
     /**
      * Test IPowerManager.acquireWakeLock() with a IWakeLockCallback.
      */
@@ -3443,6 +3456,106 @@
     }
 
     @Test
+    public void testAddWakeLockKeepingScreenOn_addsToNotifierAndReportsTimeoutPolicyChange() {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY))
+                .thenReturn(displayInfo);
+
+        createService();
+        startSystem();
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        mService.getBinderServiceInstance().addScreenTimeoutPolicyListener(
+                Display.DEFAULT_DISPLAY_GROUP, listener);
+        verify(mNotifierMock).addScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_ACTIVE, listener);
+        clearInvocations(mNotifierMock);
+
+        acquireWakeLock("screenBright", PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+                    Display.DEFAULT_DISPLAY);
+        verify(mNotifierMock).notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+    }
+
+    @Test
+    public void test_addAndRemoveScreenTimeoutListener_propagatesToNotifier()
+            throws Exception {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY))
+                .thenReturn(displayInfo);
+
+        createService();
+        startSystem();
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        mService.getBinderServiceInstance().addScreenTimeoutPolicyListener(
+                Display.DEFAULT_DISPLAY, listener);
+
+        clearInvocations(mNotifierMock);
+        mService.getBinderServiceInstance().removeScreenTimeoutPolicyListener(
+                Display.DEFAULT_DISPLAY, listener);
+        verify(mNotifierMock).removeScreenTimeoutPolicyListener(Display.DEFAULT_DISPLAY,
+                listener);
+    }
+
+    @Test
+    public void test_displayIsRemoved_clearsScreenTimeoutListeners()
+            throws Exception {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY))
+                .thenReturn(displayInfo);
+
+        createService();
+        startSystem();
+        verify(mDisplayManagerMock).registerDisplayListener(
+                mDisplayListenerArgumentCaptor.capture(), any());
+        clearInvocations(mNotifierMock);
+
+        mDisplayListenerArgumentCaptor.getValue().onDisplayRemoved(Display.DEFAULT_DISPLAY);
+
+        verify(mNotifierMock).clearScreenTimeoutPolicyListeners(Display.DEFAULT_DISPLAY);
+    }
+
+    @Test
+    public void testScreenWakeLockListener_screenHasWakelocks_addsWithHeldTimeoutPolicyToNotifier()
+            throws Exception {
+        IntArray displayGroupIds = IntArray.wrap(new int[]{Display.DEFAULT_DISPLAY_GROUP});
+        when(mDisplayManagerInternalMock.getDisplayGroupIds()).thenReturn(displayGroupIds);
+
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+        when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY))
+                .thenReturn(displayInfo);
+
+        createService();
+        startSystem();
+
+        acquireWakeLock("screenBright", PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+                Display.DEFAULT_DISPLAY);
+
+        final IScreenTimeoutPolicyListener listener = Mockito.mock(
+                IScreenTimeoutPolicyListener.class);
+        mService.getBinderServiceInstance().addScreenTimeoutPolicyListener(
+                Display.DEFAULT_DISPLAY_GROUP, listener);
+        verify(mNotifierMock).notifyScreenTimeoutPolicyChanges(Display.DEFAULT_DISPLAY_GROUP,
+                SCREEN_TIMEOUT_KEEP_DISPLAY_ON);
+    }
+
+    @Test
     public void testHalAutoSuspendMode_enabledByConfiguration() {
         AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
                 new AtomicReference<>();
diff --git a/services/tests/security/intrusiondetection/src/com/android/server/security/intrusiondetection/IntrusionDetectionServiceTest.java b/services/tests/security/intrusiondetection/src/com/android/server/security/intrusiondetection/IntrusionDetectionServiceTest.java
index 5cba6b2..298d27e 100644
--- a/services/tests/security/intrusiondetection/src/com/android/server/security/intrusiondetection/IntrusionDetectionServiceTest.java
+++ b/services/tests/security/intrusiondetection/src/com/android/server/security/intrusiondetection/IntrusionDetectionServiceTest.java
@@ -350,15 +350,17 @@
         mDataAggregator.setHandler(mLooperOfDataAggregator, mockThread);
 
         SecurityEvent securityEvent = new SecurityEvent(0, new byte[0]);
-        IntrusionDetectionEvent eventOne = new IntrusionDetectionEvent(securityEvent);
+        IntrusionDetectionEvent eventOne =
+                IntrusionDetectionEvent.createForSecurityEvent(securityEvent);
 
         ConnectEvent connectEvent = new ConnectEvent(
                 "127.0.0.1", 80, null, 0);
-        IntrusionDetectionEvent eventTwo = new IntrusionDetectionEvent(connectEvent);
+        IntrusionDetectionEvent eventTwo =
+                IntrusionDetectionEvent.createForConnectEvent(connectEvent);
 
         DnsEvent dnsEvent = new DnsEvent(
                 null, new String[] {"127.0.0.1"}, 1, null, 0);
-        IntrusionDetectionEvent eventThree = new IntrusionDetectionEvent(dnsEvent);
+        IntrusionDetectionEvent eventThree = IntrusionDetectionEvent.createForDnsEvent(dnsEvent);
 
         List<IntrusionDetectionEvent> events = new ArrayList<>();
         events.add(eventOne);
@@ -581,7 +583,8 @@
 
         // call the methods on the transport object
         IntrusionDetectionEvent event =
-                new IntrusionDetectionEvent(new SecurityEvent(123, new byte[15]));
+                IntrusionDetectionEvent.createForSecurityEvent(
+                        new SecurityEvent(123, new byte[15]));
         List<IntrusionDetectionEvent> events = new ArrayList<>();
         events.add(event);
         assertTrue(transport.initialize());
diff --git a/services/tests/servicestests/assets/shortcut/dumpsys_expected.txt b/services/tests/servicestests/assets/shortcut/dumpsys_expected.txt
index eed2087..029ada3 100644
--- a/services/tests/servicestests/assets/shortcut/dumpsys_expected.txt
+++ b/services/tests/servicestests/assets/shortcut/dumpsys_expected.txt
@@ -1,7 +1,7 @@
 {
  "shortcut": [
   {
-   "userId": 0,
+   "userId": 10,
    "launchers": [
     {
      "name": "com.android.launcher.1"
@@ -55,7 +55,7 @@
    ]
   },
   {
-   "userId": 10,
+   "userId": 11,
    "launchers": [
     {
      "name": "com.android.launcher.1"
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index 71a2651..45761b6 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -1697,6 +1697,46 @@
     }
 
     /**
+     * If processPowerKeyDown is called instead of interceptPowerKeyDown (meaning the double tap
+     * gesture isn't performed), the emergency gesture is still launched.
+     */
+    @Test
+    public void testProcessPowerKeyDown_fiveInboundPresses_emergencyGestureLaunches() {
+        enableCameraGesture();
+        enableEmergencyGesture();
+
+        // First event
+        long eventTime = INITIAL_EVENT_TIME_MILLIS;
+        sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, false, false);
+
+        //Second event; call processPowerKeyDown without calling interceptPowerKeyDown
+        final long interval = POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
+        eventTime += interval;
+        KeyEvent keyEvent =
+                new KeyEvent(
+                        IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, IGNORED_REPEAT);
+        mGestureLauncherService.processPowerKeyDown(keyEvent);
+
+        verify(mMetricsLogger, never())
+                .action(eq(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE), anyInt());
+        verify(mUiEventLogger, never()).log(any());
+
+        // Presses 3 and 4 should not trigger any gesture
+        for (int i = 0; i < 2; i++) {
+            eventTime += interval;
+            sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, true, false);
+        }
+
+        // Fifth button press should still trigger the emergency flow
+        eventTime += interval;
+        sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, true, true);
+
+        verify(mUiEventLogger, times(1))
+                .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER);
+        verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
+    }
+
+    /**
      * Helper method to trigger emergency gesture by pressing button for 5 times.
      *
      * @return last event time.
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
index d8a9400..69feb1d 100644
--- a/services/tests/servicestests/src/com/android/server/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -6,5 +6,6 @@
 per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
 per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/OWNERS
 per-file GestureLauncherServiceTest.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
+per-file GestureLauncherServiceTest.java = file:/INPUT_OWNERS
 per-file PinnerServiceTest.java = file:/apct-tests/perftests/OWNERS
 per-file SecurityStateTest.java = file:/SECURITY_STATE_OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 2c1e37b..0b2a2cd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -721,54 +721,56 @@
     protected static final String SYSTEM_PACKAGE_NAME = "android";
 
     protected static final String CALLING_PACKAGE_1 = "com.android.test.1";
-    protected static final int CALLING_UID_1 = 10001;
+    protected static final int CALLING_UID_1 = 1000001;
 
     protected static final String CALLING_PACKAGE_2 = "com.android.test.2";
-    protected static final int CALLING_UID_2 = 10002;
+    protected static final int CALLING_UID_2 = 1000002;
 
     protected static final String CALLING_PACKAGE_3 = "com.android.test.3";
-    protected static final int CALLING_UID_3 = 10003;
+    protected static final int CALLING_UID_3 = 1000003;
 
     protected static final String CALLING_PACKAGE_4 = "com.android.test.4";
-    protected static final int CALLING_UID_4 = 10004;
+    protected static final int CALLING_UID_4 = 1000004;
 
     protected static final String LAUNCHER_1 = "com.android.launcher.1";
-    protected static final int LAUNCHER_UID_1 = 10011;
+    protected static final int LAUNCHER_UID_1 = 1000011;
 
     protected static final String LAUNCHER_2 = "com.android.launcher.2";
-    protected static final int LAUNCHER_UID_2 = 10012;
+    protected static final int LAUNCHER_UID_2 = 1000012;
 
     protected static final String LAUNCHER_3 = "com.android.launcher.3";
-    protected static final int LAUNCHER_UID_3 = 10013;
+    protected static final int LAUNCHER_UID_3 = 1000013;
 
     protected static final String LAUNCHER_4 = "com.android.launcher.4";
-    protected static final int LAUNCHER_UID_4 = 10014;
+    protected static final int LAUNCHER_UID_4 = 1000014;
 
     protected static final String CHOOSER_ACTIVITY_PACKAGE = "com.android.intentresolver";
-    protected static final int CHOOSER_ACTIVITY_UID = 10015;
+    protected static final int CHOOSER_ACTIVITY_UID = 1000015;
 
-    protected static final int USER_0 = UserHandle.USER_SYSTEM;
+    // Shifting primary user to 10 to support HSUM
     protected static final int USER_10 = 10;
     protected static final int USER_11 = 11;
+    protected static final int USER_12 = 12;
     protected static final int USER_P0 = 20; // profile of user 0 (MANAGED_PROFILE *not* set)
     protected static final int USER_P1 = 21; // another profile of user 0 (MANAGED_PROFILE set)
 
-    protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0);
     protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10);
     protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
+    protected static final UserHandle HANDLE_USER_12 = UserHandle.of(USER_12);
     protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
     protected static final UserHandle HANDLE_USER_P1 = UserHandle.of(USER_P1);
 
-    protected static final UserInfo USER_INFO_0 = withProfileGroupId(
-            new UserInfo(USER_0, "user0",
-                    UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 0);
-
-    protected static final UserInfo USER_INFO_10 =
-            new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED);
+    protected static final UserInfo USER_INFO_10 = withProfileGroupId(
+            new UserInfo(USER_10, "user10",
+                    UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED),
+            USER_10);
 
     protected static final UserInfo USER_INFO_11 =
             new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED);
 
+    protected static final UserInfo USER_INFO_12 =
+            new UserInfo(USER_12, "user12", UserInfo.FLAG_INITIALIZED);
+
     /*
      * Cheat: USER_P0 is a sub profile of USER_0, but it doesn't have the MANAGED_PROFILE flag set.
      * Due to a change made to LauncherApps (b/34340531), work profile apps a no longer able
@@ -778,11 +780,11 @@
      * can't access main profile's shortcuts.)
      */
     protected static final UserInfo USER_INFO_P0 = withProfileGroupId(
-            new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), 0);
+            new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), USER_10);
 
     protected static final UserInfo USER_INFO_P1 = withProfileGroupId(
             new UserInfo(USER_P1, "userP1",
-                    UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE), 0);
+                    UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE), USER_10);
 
     protected static final UserProperties USER_PROPERTIES_0 =
             new UserProperties.Builder().setItemsRestrictedOnHomeScreen(false).build();
@@ -925,14 +927,14 @@
         deleteAllSavedFiles();
 
         // Set up users.
-        mUserInfos.put(USER_0, USER_INFO_0);
         mUserInfos.put(USER_10, USER_INFO_10);
         mUserInfos.put(USER_11, USER_INFO_11);
+        mUserInfos.put(USER_12, USER_INFO_12);
         mUserInfos.put(USER_P0, USER_INFO_P0);
         mUserInfos.put(USER_P1, USER_INFO_P1);
-        mUserProperties.put(USER_0, USER_PROPERTIES_0);
-        mUserProperties.put(USER_10, USER_PROPERTIES_10);
-        mUserProperties.put(USER_11, USER_PROPERTIES_11);
+        mUserProperties.put(USER_10, USER_PROPERTIES_0);
+        mUserProperties.put(USER_11, USER_PROPERTIES_10);
+        mUserProperties.put(USER_12, USER_PROPERTIES_11);
 
         when(mMockUserManagerInternal.isUserUnlockingOrUnlocked(anyInt()))
                 .thenAnswer(inv -> {
@@ -994,16 +996,16 @@
                 mUserInfos.values().toArray(new UserInfo[0]));
 
         // User 0 and P0 are always running
-        mRunningUsers.put(USER_0, true);
-        mRunningUsers.put(USER_10, false);
+        mRunningUsers.put(USER_10, true);
         mRunningUsers.put(USER_11, false);
+        mRunningUsers.put(USER_12, false);
         mRunningUsers.put(USER_P0, true);
         mRunningUsers.put(USER_P1, true);
 
         // Unlock all users by default.
-        mUnlockedUsers.put(USER_0, true);
         mUnlockedUsers.put(USER_10, true);
         mUnlockedUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_12, true);
         mUnlockedUsers.put(USER_P0, true);
         mUnlockedUsers.put(USER_P1, true);
 
@@ -1391,7 +1393,7 @@
     }
 
     protected void setCaller(String packageName) {
-        setCaller(packageName, UserHandle.USER_SYSTEM);
+        setCaller(packageName, USER_10);
     }
 
     protected String getCallingPackage() {
@@ -2223,7 +2225,7 @@
 
         dumpsysOnLogcat("Before backup");
 
-        final byte[] payload =  mService.getBackupPayload(USER_0);
+        final byte[] payload =  mService.getBackupPayload(USER_10);
         if (ENABLE_DUMP) {
             final String xml = new String(payload);
             Log.v(TAG, "Backup payload:");
@@ -2233,7 +2235,7 @@
         }
 
         // Before doing anything else, uninstall all packages.
-        for (int userId : list(USER_0, USER_P0)) {
+        for (int userId : list(USER_10, USER_P0)) {
             for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
                     LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) {
                 uninstallPackage(userId, pkg);
@@ -2245,11 +2247,11 @@
         deleteAllSavedFiles();
 
         initService();
-        mService.applyRestore(payload, USER_0);
+        mService.applyRestore(payload, USER_10);
 
         // handleUnlockUser will perform the gone package check, but it shouldn't remove
         // shadow information.
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         dumpsysOnLogcat("After restore");
 
@@ -2257,24 +2259,24 @@
     }
 
     protected void prepareCrossProfileDataSet() {
-        mRunningUsers.put(USER_10, true); // this test needs user 10.
+        mRunningUsers.put(USER_11, true); // this test needs user 10.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
                     makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
                     makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
                     makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list()));
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -2282,79 +2284,79 @@
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
                     makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"),
                     makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0);
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
         });
 
         // Note LAUNCHER_3 has allowBackup=false.
-        runWithCaller(LAUNCHER_3, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_3, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0);
         });
-        runWithCaller(LAUNCHER_4, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_4, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_10);
         });
 
         // Launcher on a managed profile is referring ot user 0!
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_10);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0);
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10);
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_11);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_11);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"),
-                    HANDLE_USER_10);
+                    HANDLE_USER_11);
         });
 
         // Then remove some dynamic shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list()));
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
         });
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index d70ffd2..c01283a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -285,7 +285,7 @@
     }
 
     public void SetDynamicShortcuts() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.icon1);
         final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
@@ -338,7 +338,7 @@
         dumpsysOnLogcat();
 
         mInjectedCurrentTimeMillis++; // Need to advance the clock for reset to work.
-        mService.resetThrottlingInner(UserHandle.USER_SYSTEM);
+        mService.resetThrottlingInner(USER_10);
 
         dumpsysOnLogcat();
 
@@ -347,15 +347,15 @@
 
         // TODO Check max number
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
         });
     }
 
     public void AddDynamicShortcuts() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final ShortcutInfo si1 = makeShortcut("shortcut1");
         final ShortcutInfo si2 = makeShortcut("shortcut2");
@@ -395,9 +395,9 @@
 
         // TODO Check fields.
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
         });
     }
@@ -406,7 +406,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=5,"
                 + ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=1");
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final ShortcutInfo s1 = makeShortcut("s1");
         final ShortcutInfo s2 = makeShortcut("s2");
@@ -420,10 +420,11 @@
 
         // Test push as first shortcut
         mManager.pushDynamicShortcut(s1);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()), "s1");
         assertEquals(0, getCallerShortcut("s1").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_10));
 
         // Test push when other shortcuts exist
         Mockito.reset(mMockUsageStatsManagerInternal);
@@ -436,11 +437,11 @@
         assertEquals(1, getCallerShortcut("s1").getRank());
         assertEquals(2, getCallerShortcut("s2").getRank());
         verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_10));
         verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_10));
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s3"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s3"), eq(USER_10));
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
@@ -451,7 +452,7 @@
         assertEquals(2, getCallerShortcut("s4").getRank());
         assertEquals(3, getCallerShortcut("s2").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s4"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s4"), eq(USER_10));
 
         // Push existing shortcut with set rank
         Mockito.reset(mMockUsageStatsManagerInternal);
@@ -461,7 +462,7 @@
         assertEquals(2, getCallerShortcut("s2").getRank());
         assertEquals(3, getCallerShortcut("s4").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s4"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s4"), eq(USER_10));
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
@@ -476,7 +477,7 @@
         assertEquals(3, getCallerShortcut("s2").getRank());
         assertEquals(4, getCallerShortcut("s4").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s5"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s5"), eq(USER_10));
 
         // Push when max has already reached
         Mockito.reset(mMockUsageStatsManagerInternal);
@@ -487,7 +488,7 @@
         assertEquals(1, getCallerShortcut("s5").getRank());
         assertEquals(4, getCallerShortcut("s2").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s6"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s6"), eq(USER_10));
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
@@ -499,7 +500,7 @@
                 getCallerShortcut("s7").getActivity());
         assertEquals(0, getCallerShortcut("s7").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s7"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s7"), eq(USER_10));
 
         // Push to update shortcut with different activity
         Mockito.reset(mMockUsageStatsManagerInternal);
@@ -514,7 +515,7 @@
         assertEquals(2, getCallerShortcut("s3").getRank());
         assertEquals(3, getCallerShortcut("s2").getRank());
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s1"), eq(USER_10));
 
         mInjectedCurrentTimeMillis += INTERVAL; // reset
 
@@ -524,12 +525,12 @@
         s8.setRank(100);
         mManager.pushDynamicShortcut(s8);
         assertEquals(4, getCallerShortcut("s8").getRank());
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s8"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s8"), HANDLE_USER_10,
                     CACHE_OWNER_0);
             verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                    eq(CALLING_PACKAGE_1), eq("s8"), eq(USER_0));
+                    eq(CALLING_PACKAGE_1), eq("s8"), eq(USER_10));
         });
 
         Mockito.reset(mMockUsageStatsManagerInternal);
@@ -540,7 +541,7 @@
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s8");
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s9"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s9"), eq(USER_10));
     }
 
     public void PushDynamicShortcut_CallsToUsageStatsManagerAreThrottled()
@@ -549,13 +550,13 @@
                 ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=500");
 
         // Verify calls to UsageStatsManagerInternal#reportShortcutUsage are throttled.
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         {
             final ShortcutInfo si = makeShortcut("s0");
             mManager.pushDynamicShortcut(si);
         }
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), eq("s0"), eq(USER_0));
+                eq(CALLING_PACKAGE_1), eq("s0"), eq(USER_10));
         Mockito.reset(mMockUsageStatsManagerInternal);
         for (int i = 2; i <= 10; i++) {
             final ShortcutInfo si = makeShortcut("s" + i);
@@ -565,13 +566,13 @@
                 any(), any(), anyInt());
 
         // Verify pkg2 isn't blocked by pkg1, but consecutive calls from pkg2 are throttled as well.
-        setCaller(CALLING_PACKAGE_2, USER_0);
+        setCaller(CALLING_PACKAGE_2, USER_10);
         {
             final ShortcutInfo si = makeShortcut("s1");
             mManager.pushDynamicShortcut(si);
         }
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_2), eq("s1"), eq(USER_0));
+                eq(CALLING_PACKAGE_2), eq("s1"), eq(USER_10));
         Mockito.reset(mMockUsageStatsManagerInternal);
         for (int i = 2; i <= 10; i++) {
             final ShortcutInfo si = makeShortcut("s" + i);
@@ -584,18 +585,18 @@
         // Let time passes which resets the throttle
         Thread.sleep(505);
         // Verify UsageStatsManagerInternal#reportShortcutUsed can be called again
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.pushDynamicShortcut(makeShortcut("s10"));
-        setCaller(CALLING_PACKAGE_2, USER_0);
+        setCaller(CALLING_PACKAGE_2, USER_10);
         mManager.pushDynamicShortcut(makeShortcut("s10"));
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_1), any(), eq(USER_0));
+                eq(CALLING_PACKAGE_1), any(), eq(USER_10));
         verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                eq(CALLING_PACKAGE_2), any(), eq(USER_0));
+                eq(CALLING_PACKAGE_2), any(), eq(USER_10));
     }
 
     public void UnlimitedCalls() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final ShortcutInfo si1 = makeShortcut("shortcut1");
 
@@ -628,9 +629,9 @@
     public void PublishWithNoActivity() {
         // If activity is not explicitly set, use the default one.
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             // s1 and s3 has no activities.
             final ShortcutInfo si1 = new ShortcutInfo.Builder(mClientContext, "si1")
                     .setShortLabel("label1")
@@ -732,9 +733,9 @@
     }
 
     public void PublishWithNoActivity_noMainActivityInPackage() {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             final ShortcutInfo si1 = new ShortcutInfo.Builder(mClientContext, "si1")
                     .setShortLabel("label1")
                     .setIntent(new Intent("action1"))
@@ -905,35 +906,35 @@
         setCaller(LAUNCHER_1);
         // Check hasIconResource()/hasIconFile().
         assertShortcutIds(assertAllHaveIconResId(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_10))),
                 "res32x32");
 
         assertShortcutIds(assertAllHaveIconResId(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_10))),
                 "res64x64");
 
         assertShortcutIds(assertAllHaveIconFile(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_10))),
                 "bmp32x32");
 
         assertShortcutIds(assertAllHaveIconFile(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_10))),
                 "bmp64x64");
 
         assertShortcutIds(assertAllHaveIconFile(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_10))),
                 "bmp512x512");
 
         assertShortcutIds(assertAllHaveIconUri(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri32x32", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri32x32", USER_10))),
                 "uri32x32");
 
         assertShortcutIds(assertAllHaveIconUri(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri64x64", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri64x64", USER_10))),
                 "uri64x64");
 
         assertShortcutIds(assertAllHaveIconUri(
-                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri512x512", USER_0))),
+                list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri512x512", USER_10))),
                 "uri512x512");
 
         assertShortcutIds(assertAllHaveIconResId(
@@ -947,36 +948,36 @@
         assertEquals(
                 R.drawable.black_32x32,
                 mLauncherApps.getShortcutIconResId(
-                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_0)));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_10)));
 
         assertEquals(
                 R.drawable.black_64x64,
                 mLauncherApps.getShortcutIconResId(
-                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_0)));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res64x64", USER_10)));
 
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_10)));
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_10)));
         assertEquals(
                 0, // because it's not a resource
                 mLauncherApps.getShortcutIconResId(
-                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
+                        getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_10)));
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_0)));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp32x32", USER_10)));
         assertBitmapSize(32, 32, bmp);
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_0)));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp64x64", USER_10)));
         assertBitmapSize(64, 64, bmp);
 
         bmp = pfdToBitmap(mLauncherApps.getShortcutIconFd(
-                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0)));
+                getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_10)));
         assertBitmapSize(128, 128, bmp);
 
         assertEquals(
@@ -991,10 +992,10 @@
         // Also check the overload APIs too.
         assertEquals(
                 R.drawable.black_32x32,
-                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_0));
+                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_10));
         assertEquals(
                 R.drawable.black_64x64,
-                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res64x64", HANDLE_USER_0));
+                mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res64x64", HANDLE_USER_10));
         assertEquals(
                 R.drawable.black_512x512,
                 mLauncherApps.getShortcutIconResId(CALLING_PACKAGE_1, "res32x32", HANDLE_USER_P0));
@@ -1035,14 +1036,14 @@
     }
 
     public void CleanupDanglingBitmaps() throws Exception {
-        assertBitmapDirectories(USER_0, EMPTY_STRINGS);
         assertBitmapDirectories(USER_10, EMPTY_STRINGS);
+        assertBitmapDirectories(USER_11, EMPTY_STRINGS);
 
         // Make some shortcuts with bitmap icons.
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("s1", bmp32x32),
                     makeShortcutWithIcon("s2", bmp32x32),
@@ -1053,7 +1054,7 @@
         // Increment the time (which actually we don't have to), which is used for filenames.
         mInjectedCurrentTimeMillis++;
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("s4", bmp32x32),
                     makeShortcutWithIcon("s5", bmp32x32),
@@ -1064,29 +1065,29 @@
         // Increment the time, which is used for filenames.
         mInjectedCurrentTimeMillis++;
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             mManager.setDynamicShortcuts(list(
             ));
         });
 
         // For USER-10, let's try without updating the times.
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("10s1", bmp32x32),
                     makeShortcutWithIcon("10s2", bmp32x32),
                     makeShortcutWithIcon("10s3", bmp32x32)
             ));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("10s4", bmp32x32),
                     makeShortcutWithIcon("10s5", bmp32x32),
                     makeShortcutWithIcon("10s6", bmp32x32)
             ));
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_11, () -> {
             mManager.setDynamicShortcuts(list(
             ));
         });
@@ -1096,104 +1097,104 @@
         mService.waitForBitmapSavesForTest();
         // Check files and directories.
         // Package 3 has no bitmaps, so we don't create a directory.
-        assertBitmapDirectories(USER_0, CALLING_PACKAGE_1, CALLING_PACKAGE_2);
         assertBitmapDirectories(USER_10, CALLING_PACKAGE_1, CALLING_PACKAGE_2);
+        assertBitmapDirectories(USER_11, CALLING_PACKAGE_1, CALLING_PACKAGE_2);
 
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_1,
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s1"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s2"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s3")
-        );
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_2,
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s4"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s5"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s6")
-        );
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_3,
-                EMPTY_STRINGS
-        );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_1,
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s1"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s2"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s3")
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s1"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s2"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s3")
         );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_2,
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s4"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s5"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s6")
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s4"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s5"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s6")
         );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_3,
                 EMPTY_STRINGS
         );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_1,
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s1"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s2"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s3")
+        );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_2,
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s4"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s5"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s6")
+        );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_3,
+                EMPTY_STRINGS
+        );
 
         // Then create random directories and files.
-        makeFile(mService.getUserBitmapFilePath(USER_0), "a.b.c").mkdir();
-        makeFile(mService.getUserBitmapFilePath(USER_0), "d.e.f").mkdir();
-        makeFile(mService.getUserBitmapFilePath(USER_0), "d.e.f", "123").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_0), "d.e.f", "456").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), "a.b.c").mkdir();
+        makeFile(mService.getUserBitmapFilePath(USER_10), "d.e.f").mkdir();
+        makeFile(mService.getUserBitmapFilePath(USER_10), "d.e.f", "123").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), "d.e.f", "456").createNewFile();
 
-        makeFile(mService.getUserBitmapFilePath(USER_0), CALLING_PACKAGE_3).mkdir();
+        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_3).mkdir();
 
-        makeFile(mService.getUserBitmapFilePath(USER_0), CALLING_PACKAGE_1, "1").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_0), CALLING_PACKAGE_1, "2").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_0), CALLING_PACKAGE_1, "3").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_0), CALLING_PACKAGE_1, "4").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_1, "1").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_1, "2").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_1, "3").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_1, "4").createNewFile();
 
-        makeFile(mService.getUserBitmapFilePath(USER_10), "10a.b.c").mkdir();
-        makeFile(mService.getUserBitmapFilePath(USER_10), "10d.e.f").mkdir();
-        makeFile(mService.getUserBitmapFilePath(USER_10), "10d.e.f", "123").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_10), "10d.e.f", "456").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), "10a.b.c").mkdir();
+        makeFile(mService.getUserBitmapFilePath(USER_11), "10d.e.f").mkdir();
+        makeFile(mService.getUserBitmapFilePath(USER_11), "10d.e.f", "123").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), "10d.e.f", "456").createNewFile();
 
-        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_2, "1").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_2, "2").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_2, "3").createNewFile();
-        makeFile(mService.getUserBitmapFilePath(USER_10), CALLING_PACKAGE_2, "4").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), CALLING_PACKAGE_2, "1").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), CALLING_PACKAGE_2, "2").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), CALLING_PACKAGE_2, "3").createNewFile();
+        makeFile(mService.getUserBitmapFilePath(USER_11), CALLING_PACKAGE_2, "4").createNewFile();
 
         mService.waitForBitmapSavesForTest();
-        assertBitmapDirectories(USER_0, CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
+        assertBitmapDirectories(USER_10, CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
                 "a.b.c", "d.e.f");
 
         // Save and load.  When a user is loaded, we do the cleanup.
         mService.saveDirtyInfo();
         initService();
 
-        mService.handleUnlockUser(USER_0);
         mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
         mService.handleUnlockUser(20); // Make sure the logic will still work for nonexistent user.
 
         // The below check is the same as above, except this time USER_0 use the CALLING_PACKAGE_3
         // directory.
 
         mService.waitForBitmapSavesForTest();
-        assertBitmapDirectories(USER_0, CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3);
-        assertBitmapDirectories(USER_10, CALLING_PACKAGE_1, CALLING_PACKAGE_2);
+        assertBitmapDirectories(USER_10, CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3);
+        assertBitmapDirectories(USER_11, CALLING_PACKAGE_1, CALLING_PACKAGE_2);
 
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_1,
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s1"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s2"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_1, "s3")
-        );
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_2,
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s4"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s5"),
-                getBitmapFilename(USER_0, CALLING_PACKAGE_2, "s6")
-        );
-        assertBitmapFiles(USER_0, CALLING_PACKAGE_3,
-                EMPTY_STRINGS
-        );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_1,
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s1"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s2"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "10s3")
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s1"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s2"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_1, "s3")
         );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_2,
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s4"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s5"),
-                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "10s6")
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s4"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s5"),
+                getBitmapFilename(USER_10, CALLING_PACKAGE_2, "s6")
         );
         assertBitmapFiles(USER_10, CALLING_PACKAGE_3,
                 EMPTY_STRINGS
         );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_1,
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s1"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s2"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_1, "10s3")
+        );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_2,
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s4"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s5"),
+                getBitmapFilename(USER_11, CALLING_PACKAGE_2, "10s6")
+        );
+        assertBitmapFiles(USER_11, CALLING_PACKAGE_3,
+                EMPTY_STRINGS
+        );
     }
 
     protected void checkShrinkBitmap(int expectedWidth, int expectedHeight, int resId, int maxSize) {
@@ -1301,7 +1302,7 @@
     }
 
     public void UpdateShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcut("s2"),
@@ -1310,7 +1311,7 @@
                     makeShortcut("s5")
             )));
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcut("s2"),
@@ -1319,22 +1320,22 @@
                     makeShortcut("s5")
             )));
         });
-        runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
                     getCallingUser());
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
                     getCallingUser());
         });
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s2"));
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s3"));
             mManager.removeDynamicShortcuts(list("s5"));
         });
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
                     "s3", "s4", "s5");
@@ -1342,7 +1343,7 @@
                     mManager.getPinnedShortcuts()),
                     "s2", "s3");
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
                     "s2", "s4");
@@ -1351,7 +1352,7 @@
                     "s4", "s5");
         });
 
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             ShortcutInfo s2 = makeShortcutBuilder()
                     .setId("s2")
                     .setIcon(Icon.createWithResource(getTestContext(), R.drawable.black_32x32))
@@ -1364,7 +1365,7 @@
 
             mManager.updateShortcuts(list(s2, s4));
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             ShortcutInfo s2 = makeShortcutBuilder()
                     .setId("s2")
                     .setIntent(makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
@@ -1379,7 +1380,7 @@
             mManager.updateShortcuts(list(s2, s4));
         });
 
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
                     "s3", "s4", "s5");
@@ -1398,7 +1399,7 @@
             assertEquals(0, s.getIconResourceId());
             assertEquals("new title", s.getTitle());
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
                     "s2", "s4");
@@ -1424,15 +1425,15 @@
 
         // TODO Check bitmap removal too.
 
-        mRunningUsers.put(USER_11, true);
+        mRunningUsers.put(USER_12, true);
 
-        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_12, () -> {
             mManager.updateShortcuts(list());
         });
     }
 
     public void UpdateShortcuts_icons() {
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1")
             )));
@@ -1533,26 +1534,26 @@
                 R.xml.shortcut_3);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeLongLivedShortcut("s1"), makeLongLivedShortcut("s2"), makeShortcut("s3"))));
         });
 
         // Pin 2 and 3
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "ms3", "s2", "s3"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_10);
         });
 
         // Cache 1 and 2
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"),
-                    HANDLE_USER_0, CACHE_OWNER_1);
+                    HANDLE_USER_10, CACHE_OWNER_1);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1617,7 +1618,7 @@
     }
 
     public void CachedShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
                     makeLongLivedShortcut("s4"), makeLongLivedShortcut("s5"),
@@ -1625,20 +1626,20 @@
         });
 
         // Pin s2
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_10);
         });
 
         // Cache some, but non long lived shortcuts will be ignored.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4", "s5"),
-                    HANDLE_USER_0, CACHE_OWNER_1);
+                    HANDLE_USER_10, CACHE_OWNER_1);
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s5", "s6"),
-                    HANDLE_USER_0, CACHE_OWNER_2);
+                    HANDLE_USER_10, CACHE_OWNER_2);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1660,32 +1661,32 @@
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s4", "s5", "s6");
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
         // s2 still cached by owner1. s4 wasn't cached by owner0 so didn't get removed.
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s4", "s5", "s6");
 
         // uncache a non-dynamic shortcut. Should be removed.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s4"),
-                    HANDLE_USER_0, CACHE_OWNER_1);
+                    HANDLE_USER_10, CACHE_OWNER_1);
         });
 
         // uncache s6 by its only owner. s5 still cached by owner1
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s5", "s6"),
-                    HANDLE_USER_0, CACHE_OWNER_2);
+                    HANDLE_USER_10, CACHE_OWNER_2);
         });
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s5");
 
         // Cache another shortcut
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
                 "s2", "s3", "s5");
@@ -1701,24 +1702,24 @@
     }
 
     public void CachedShortcuts_accessShortcutsPermission() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
                     makeLongLivedShortcut("s4"))));
         });
 
         // s1 is not long lived and will be ignored.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = false;
             assertExpectException(
                     SecurityException.class, "Caller can't access shortcut information", () -> {
                         mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"),
-                                HANDLE_USER_0, CACHE_OWNER_0);
+                                HANDLE_USER_10, CACHE_OWNER_0);
                     });
             // Give ACCESS_SHORTCUTS permission to LAUNCHER_1
             mInjectCheckAccessShortcutsPermission = true;
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -1726,17 +1727,17 @@
         // Get cached shortcuts
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s2", "s3");
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = false;
             assertExpectException(
                     SecurityException.class, "Caller can't access shortcut information", () -> {
                         mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4"),
-                                HANDLE_USER_0, CACHE_OWNER_0);
+                                HANDLE_USER_10, CACHE_OWNER_0);
                     });
             // Give ACCESS_SHORTCUTS permission to LAUNCHER_1
             mInjectCheckAccessShortcutsPermission = true;
             mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2", "s4"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
 
         assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED), "s3");
@@ -1746,17 +1747,17 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=4");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"),
                     makeLongLivedShortcut("s4"))));
         });
 
         // Cache All
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
             mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3", "s4"),
-                    HANDLE_USER_0, CACHE_OWNER_0);
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
 
         setCaller(CALLING_PACKAGE_1);
@@ -2004,17 +2005,17 @@
                 R.xml.shortcut_3);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
         // Pin 2 and 3
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "ms3", "s2", "s3"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_10);
         });
 
         // Remove ms3 and s3
@@ -2023,15 +2024,15 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
         });
 
         // Check their status.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3")
 
@@ -2071,45 +2072,45 @@
         });
 
         // Finally, actual tests.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertWith(mLauncherApps.getShortcuts(
-                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0))
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10))
                     .haveIds("s1", "s2");
             assertWith(mLauncherApps.getShortcuts(
-                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_MANIFEST), HANDLE_USER_0))
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_MANIFEST), HANDLE_USER_10))
                     .haveIds("ms1", "ms2");
             assertWith(mLauncherApps.getShortcuts(
-                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0))
+                    buildQueryWithFlags(ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10))
                     .haveIds("s2", "s3", "ms2", "ms3");
 
             assertWith(mLauncherApps.getShortcuts(
                     buildQueryWithFlags(
                             ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED
-                    ), HANDLE_USER_0))
+                    ), HANDLE_USER_10))
                     .haveIds("s1", "s2", "s3", "ms2", "ms3");
 
             assertWith(mLauncherApps.getShortcuts(
                     buildQueryWithFlags(
                             ShortcutQuery.FLAG_GET_MANIFEST | ShortcutQuery.FLAG_GET_PINNED
-                    ), HANDLE_USER_0))
+                    ), HANDLE_USER_10))
                     .haveIds("ms1", "s2", "s3", "ms2", "ms3");
 
             assertWith(mLauncherApps.getShortcuts(
                     buildQueryWithFlags(
                             ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_MANIFEST
-                    ), HANDLE_USER_0))
+                    ), HANDLE_USER_10))
                     .haveIds("ms1", "ms2", "s1", "s2");
 
             assertWith(mLauncherApps.getShortcuts(
                     buildQueryWithFlags(
                             ShortcutQuery.FLAG_GET_ALL_KINDS
-                    ), HANDLE_USER_0))
+                    ), HANDLE_USER_10))
                     .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3");
         });
     }
 
     public void GetShortcuts_resolveStrings() throws Exception {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             ShortcutInfo si = new ShortcutInfo.Builder(mClientContext)
                     .setId("id")
                     .setActivity(new ComponentName(mClientContext, "dummy"))
@@ -2132,17 +2133,17 @@
             mManager.setDynamicShortcuts(list(si));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             final ShortcutQuery q = new ShortcutQuery();
             q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC);
 
             // USER 0
             List<ShortcutInfo> ret = assertShortcutIds(
-                    assertAllStringsResolved(mLauncherApps.getShortcuts(q, HANDLE_USER_0)),
+                    assertAllStringsResolved(mLauncherApps.getShortcuts(q, HANDLE_USER_10)),
                     "id");
-            assertEquals("string-com.android.test.1-user:0-res:10/en", ret.get(0).getTitle());
-            assertEquals("string-com.android.test.1-user:0-res:11/en", ret.get(0).getText());
-            assertEquals("string-com.android.test.1-user:0-res:12/en",
+            assertEquals("string-com.android.test.1-user:10-res:10/en", ret.get(0).getTitle());
+            assertEquals("string-com.android.test.1-user:10-res:11/en", ret.get(0).getText());
+            assertEquals("string-com.android.test.1-user:10-res:12/en",
                     ret.get(0).getDisabledMessage());
 
             // USER P0
@@ -2280,27 +2281,27 @@
     }
 
     public void PinShortcutAndGetPinnedShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
             final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
 
             assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
             final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
             final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
             assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
             assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
         });
 
         // Pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s2", "s3"), getCallingUser());
 
@@ -2312,7 +2313,7 @@
         });
 
         // Delete some.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
             mManager.removeDynamicShortcuts(list("s2"));
             assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
@@ -2320,7 +2321,7 @@
             assertShortcutIds(mManager.getDynamicShortcuts(), "s1");
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
             mManager.removeDynamicShortcuts(list("s3"));
             assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
@@ -2328,7 +2329,7 @@
             assertShortcutIds(mManager.getDynamicShortcuts(), "s2", "s4");
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
             mManager.removeDynamicShortcuts(list("s2"));
             assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
@@ -2337,7 +2338,7 @@
         });
 
         // Get pinned shortcuts from launcher
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(assertAllEnabled(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
@@ -2361,27 +2362,27 @@
      * does "enable".
      */
     public void DisableAndEnableShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
             final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
 
             assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
             final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
             final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
             assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
             assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
         });
 
         // Pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s2", "s3"), getCallingUser());
 
@@ -2393,7 +2394,7 @@
         });
 
         // Disable some.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
 
             mManager.updateShortcuts(list(
@@ -2406,7 +2407,7 @@
             assertShortcutIds(mManager.getDynamicShortcuts(), "s1");
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
 
             // disable should work even if a shortcut is not dynamic, so try calling "remove" first
@@ -2418,7 +2419,7 @@
             assertShortcutIds(mManager.getDynamicShortcuts(), "s2", "s4");
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
 
             mManager.disableShortcuts(list("s2"));
@@ -2430,7 +2431,7 @@
         });
 
         // Get pinned shortcuts from launcher
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists, and disabled.
             assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))
@@ -2442,7 +2443,7 @@
                     .areAllPinned()
                     .areAllNotWithKeyFieldsOnly()
                     .areAllDisabled();
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
                     ActivityNotFoundException.class);
 
             // Here, s4 is still enabled and launchable, but s3 is disabled.
@@ -2459,9 +2460,9 @@
                     .selectByIds("s4")
                     .areAllEnabled();
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s3", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s3", USER_10,
                     ActivityNotFoundException.class);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s4", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s4", USER_10);
 
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(assertAllEnabled(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3,
@@ -2469,30 +2470,30 @@
                     /* none */);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.enableShortcuts(list("s2"));
 
             assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
             assertShortcutIds(mManager.getDynamicShortcuts(), "s1");
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(assertAllEnabled(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))),
                     "s2");
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
         });
     }
 
     public void DisableShortcuts_thenRepublish() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
 
-            runWithCaller(LAUNCHER_1, USER_0, () -> {
+            runWithCaller(LAUNCHER_1, USER_10, () -> {
                 mLauncherApps.pinShortcuts(
-                        CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_0);
+                        CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_10);
             });
 
             mManager.disableShortcuts(list("s1", "s2", "s3"));
@@ -2557,12 +2558,12 @@
 
     public void PinShortcutAndGetPinnedShortcuts_multi() {
         // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
@@ -2570,7 +2571,7 @@
         dumpsysOnLogcat();
 
         // Pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s3", "s4"), getCallingUser());
 
@@ -2581,7 +2582,7 @@
         dumpsysOnLogcat();
 
         // Delete some.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
             mManager.removeDynamicShortcuts(list("s3"));
             assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
@@ -2589,7 +2590,7 @@
 
         dumpsysOnLogcat();
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2");
             mManager.removeDynamicShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s3"));
@@ -2599,7 +2600,7 @@
         dumpsysOnLogcat();
 
         // Get pinned shortcuts from launcher
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
@@ -2625,7 +2626,7 @@
 
         dumpsysOnLogcat("Before launcher 2");
 
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             // Launcher2 still has no pinned ones.
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
@@ -2698,10 +2699,10 @@
         initService();
 
         // Load from file.
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Make sure package info is restored too.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
@@ -2711,7 +2712,7 @@
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
                     "s1", "s2");
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED
@@ -2725,20 +2726,20 @@
         });
 
         // Delete all dynamic.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
 
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
 
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1");
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
@@ -2766,13 +2767,13 @@
                     "s3");
         });
         // Re-publish s1.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
 
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3");
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
@@ -2789,7 +2790,7 @@
         });
 
         // Now clear pinned shortcuts.  First, from launcher 1.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), getCallingUser());
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), getCallingUser());
 
@@ -2800,17 +2801,17 @@
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2");
         });
 
         // Clear all pins from launcher 2.
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), getCallingUser());
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), getCallingUser());
 
@@ -2821,11 +2822,11 @@
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1");
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
@@ -2833,108 +2834,108 @@
 
     public void PinShortcutAndGetPinnedShortcuts_assistant() {
         // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
         // Pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s3", "s4"), getCallingUser());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"))));
         });
 
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             final ShortcutQuery allPinned = new ShortcutQuery().setQueryFlags(
                     ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER);
 
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .isEmpty();
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s3", USER_0);
-            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_10);
 
             // Make it the assistant app.
-            mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_0);
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_10);
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .haveIds("s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
-            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s4", USER_10);
 
-            mInternal.setShortcutHostPackage("another-type", LAUNCHER_3, USER_0);
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            mInternal.setShortcutHostPackage("another-type", LAUNCHER_3, USER_10);
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .haveIds("s3");
 
-            mInternal.setShortcutHostPackage("assistant", null, USER_0);
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            mInternal.setShortcutHostPackage("assistant", null, USER_10);
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .isEmpty();
 
-            mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_0);
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            mInternal.setShortcutHostPackage("assistant", LAUNCHER_2, USER_10);
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .haveIds("s3");
 
-            mInternal.setShortcutHostPackage("assistant", LAUNCHER_1, USER_0);
-            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_0))
+            mInternal.setShortcutHostPackage("assistant", LAUNCHER_1, USER_10);
+            assertWith(mLauncherApps.getShortcuts(allPinned, HANDLE_USER_10))
                     .isEmpty();
         });
     }
 
     public void PinShortcutAndGetPinnedShortcuts_crossProfile_plusLaunch() {
         // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
-        });
-
-        mRunningUsers.put(USER_10, true);
-
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        mRunningUsers.put(USER_11, true);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
                     makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
         });
 
         // Pin some shortcuts and see the result.
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s1"), HANDLE_USER_0);
+                    list("s1"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s1", "s2", "s3"), HANDLE_USER_0);
+                    list("s1", "s2", "s3"), HANDLE_USER_10);
         });
 
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s2"), HANDLE_USER_0);
+                    list("s2"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s2", "s3"), HANDLE_USER_0);
+                    list("s2", "s3"), HANDLE_USER_10);
         });
 
         runWithCaller(LAUNCHER_2, USER_P0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s3"), HANDLE_USER_0);
+                    list("s3"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s3"), HANDLE_USER_0);
+                    list("s3"), HANDLE_USER_10);
         });
 
-        runWithCaller(LAUNCHER_2, USER_10, () -> {
+        runWithCaller(LAUNCHER_2, USER_11, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s1", "s2", "s3"), HANDLE_USER_10);
+                    list("s1", "s2", "s3"), HANDLE_USER_11);
         });
 
         // First, make sure managed profile can't see other profiles.
@@ -2945,347 +2946,198 @@
                             | ShortcutQuery.FLAG_MATCH_MANIFEST);
 
             // No shortcuts are visible.
-            assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_0)).isEmpty();
+            assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_10)).isEmpty();
 
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10);
 
             // Should have no effects.
-            assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_0)).isEmpty();
+            assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_10)).isEmpty();
 
-            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunched(CALLING_PACKAGE_1, "s1", USER_10);
         });
 
         // Cross profile pinning.
         final int PIN_AND_DYNAMIC = ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC;
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
 
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     SecurityException.class);
         });
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s2");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s2", "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
 
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     SecurityException.class);
         });
         runWithCaller(LAUNCHER_2, USER_P0, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
-                    SecurityException.class);
-        });
-        runWithCaller(LAUNCHER_2, USER_10, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
-                    "s1", "s2", "s3");
+                    "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
-                    "s1", "s2", "s3", "s4", "s5", "s6");
+                    "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
+                    SecurityException.class);
+        });
+        runWithCaller(LAUNCHER_2, USER_11, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_11)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_11)),
+                    "s1", "s2", "s3", "s4", "s5", "s6");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_11)),
                     "s1", "s2", "s3", "s4", "s5", "s6");
         });
 
         // Remove some dynamic shortcuts.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"))));
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s1"))));
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"))));
         });
-
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_0,
-                    ActivityNotFoundException.class);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
-                    SecurityException.class);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
         });
-        runWithCaller(LAUNCHER_1, USER_P0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s2");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2");
-
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s2", "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s2", "s3");
-
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_0,
-                    ActivityNotFoundException.class);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
-                    SecurityException.class);
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
         });
-        runWithCaller(LAUNCHER_2, USER_P0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s3");
 
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
-                    "s3");
-            assertShortcutIds(assertAllDynamic(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllDynamicOrPinned(
-                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
-                    "s1", "s3");
-
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
-                    SecurityException.class);
-        });
-        runWithCaller(LAUNCHER_2, USER_10, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
-                    "s1", "s2", "s3");
+                    "s1");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
@@ -3293,192 +3145,341 @@
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
                     /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_0,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
-                    SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_0,
-                    SecurityException.class);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+                    ActivityNotFoundException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+                    ActivityNotFoundException.class);
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s1", USER_0,
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s3", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
+                    SecurityException.class);
+        });
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
 
             assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
             assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+                    ActivityNotFoundException.class);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
+                    SecurityException.class);
+        });
+        runWithCaller(LAUNCHER_2, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+                    ActivityNotFoundException.class);
             assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_10,
                     ActivityNotFoundException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
+                    SecurityException.class);
+        });
+        runWithCaller(LAUNCHER_2, USER_11, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_11)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_11)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_11)),
+                    "s1", "s2", "s3");
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+                    SecurityException.class);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s1", USER_10,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_10,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s3", USER_10,
+                    SecurityException.class);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_11);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_11);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_11);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
                     ActivityNotFoundException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    ActivityNotFoundException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     ActivityNotFoundException.class);
         });
 
         // Save & load and make sure we still have the same information.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1");
 
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_0,
-                    ActivityNotFoundException.class);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
             assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
-                    SecurityException.class);
+                    ActivityNotFoundException.class);
             assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+                    ActivityNotFoundException.class);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     SecurityException.class);
         });
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s2");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2");
 
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s2", "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s2", "s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_0,
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
                     ActivityNotFoundException.class);
 
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
 
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     SecurityException.class);
         });
         runWithCaller(LAUNCHER_2, USER_P0, () -> {
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s3");
 
             assertShortcutIds(assertAllPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
                     "s3");
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
                     "s1");
             assertShortcutIds(assertAllDynamicOrPinned(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
-                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
                     "s1", "s3");
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
-
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_0,
-                    ActivityNotFoundException.class);
-            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
-
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
-                    SecurityException.class);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
             assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_10,
+                    ActivityNotFoundException.class);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_10);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_2, "s2", USER_10,
+                    ActivityNotFoundException.class);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_10);
+
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s2", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s3", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s4", USER_11,
                     SecurityException.class);
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_10,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s5", USER_11,
+                    SecurityException.class);
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s6", USER_11,
                     SecurityException.class);
         });
     }
 
     public void StartShortcut() {
         // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ShortcutInfo s1_1 = makeShortcut(
                     "s1",
                     "Title 1",
@@ -3503,7 +3504,7 @@
             assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2, s1_3)));
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             final ShortcutInfo s2_1 = makeShortcut(
                     "s1",
                     "ABC",
@@ -3516,7 +3517,7 @@
         });
 
         // Pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s1", "s2"), getCallingUser());
 
@@ -3525,12 +3526,12 @@
         });
 
         // Just to make it complicated, delete some.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s2"));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_10);
             assertEquals(ShortcutActivity2.class.getName(),
                     intents[0].getComponent().getClassName());
             assertEquals(Intent.ACTION_ASSIST,
@@ -3545,25 +3546,25 @@
 
             assertEquals(
                     ShortcutActivity3.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
+                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_10)
                             .getComponent().getClassName());
             assertEquals(
                     ShortcutActivity.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0)
+                    launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_10)
                             .getComponent().getClassName());
 
-            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
 
-            assertShortcutNotLaunched("no-such-package", "s2", USER_0);
-            assertShortcutNotLaunched(CALLING_PACKAGE_1, "xxxx", USER_0);
+            assertShortcutNotLaunched("no-such-package", "s2", USER_10);
+            assertShortcutNotLaunched(CALLING_PACKAGE_1, "xxxx", USER_10);
         });
 
         // LAUNCHER_1 is no longer the default launcher
         setDefaultLauncherChecker((pkg, userId) -> false);
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Not the default launcher, but pinned shortcuts are still lauchable.
-            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_0);
+            final Intent[] intents = launchShortcutAndGetIntents(CALLING_PACKAGE_1, "s1", USER_10);
             assertEquals(ShortcutActivity2.class.getName(),
                     intents[0].getComponent().getClassName());
             assertEquals(Intent.ACTION_ASSIST,
@@ -3577,24 +3578,24 @@
                     intents[1].getFlags());
             assertEquals(
                     ShortcutActivity3.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
+                    launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_10)
                             .getComponent().getClassName());
             assertEquals(
                     ShortcutActivity.class.getName(),
-                    launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0)
+                    launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_10)
                             .getComponent().getClassName());
 
             // Not pinned, so not lauchable.
         });
 
         // Test inner errors.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Not launchable.
             doReturn(ActivityManager.START_CLASS_NOT_FOUND)
                     .when(mMockActivityTaskManagerInternal).startActivitiesAsPackage(
                     anyStringOrNull(), anyStringOrNull(), anyInt(),
                     anyOrNull(Intent[].class), anyOrNull(Bundle.class));
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
                     ActivityNotFoundException.class);
 
             // Still not launchable.
@@ -3603,7 +3604,7 @@
                     .startActivitiesAsPackage(
                             anyStringOrNull(), anyStringOrNull(), anyInt(),
                             anyOrNull(Intent[].class), anyOrNull(Bundle.class));
-            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_0,
+            assertStartShortcutThrowsException(CALLING_PACKAGE_1, "s1", USER_10,
                     ActivityNotFoundException.class);
         });
 
@@ -3618,34 +3619,34 @@
                         + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
         );
 
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
 
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 assertTrue(mManager.setDynamicShortcuts(list(
                         makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .haveIds("s1", "s2", "s3")
                 .areAllWithKeyFieldsOnly()
                 .areAllDynamic();
 
         // From different package.
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
                 assertTrue(mManager.setDynamicShortcuts(list(
                         makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_10)
                 .haveIds("s1", "s2", "s3")
                 .areAllWithKeyFieldsOnly()
                 .areAllDynamic();
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         // Different user, callback shouldn't be called.
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
                 assertTrue(mManager.setDynamicShortcuts(list(
                         makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
             });
@@ -3654,31 +3655,31 @@
 
         // Test for addDynamicShortcuts.
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s4"))));
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .haveIds("s1", "s2", "s3", "s4")
                 .areAllWithKeyFieldsOnly()
                 .areAllDynamic();
 
         // Test for remove
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 mManager.removeDynamicShortcuts(list("s1"));
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .haveIds("s2", "s3", "s4")
                 .areAllWithKeyFieldsOnly()
                 .areAllDynamic();
 
         // Test for update
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 assertTrue(mManager.updateShortcuts(list(
                         makeShortcut("s1"), makeShortcut("s2"))));
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 // All remaining shortcuts will be passed regardless of what's been updated.
                 .haveIds("s2", "s3", "s4")
                 .areAllWithKeyFieldsOnly()
@@ -3686,10 +3687,10 @@
 
         // Test for deleteAll
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 mManager.removeAllDynamicShortcuts();
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .isEmpty();
 
         // Update package1 with manifest shortcuts
@@ -3699,24 +3700,24 @@
                     R.xml.shortcut_2);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
             mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .areAllManifest()
                 .areAllWithKeyFieldsOnly()
                 .haveIds("ms1", "ms2");
 
         // Make sure pinned shortcuts are passed too.
         // 1. Add dynamic shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
         });
 
         // 2. Pin some.
-        runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
         });
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "s1", "s2")
                     .areAllEnabled()
@@ -3736,10 +3737,10 @@
                 R.xml.shortcut_0);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         assertForLauncherCallback(mLauncherApps, () -> {
-            runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
                 mManager.removeDynamicShortcuts(list("s2"));
 
                 assertWith(getCallerShortcuts())
@@ -3764,16 +3765,16 @@
                         .areAllEnabled()
                 ;
             });
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .haveIds("ms2", "s1", "s2")
                 .areAllWithKeyFieldsOnly();
 
         // Remove CALLING_PACKAGE_2
         assertForLauncherCallback(mLauncherApps, () -> {
-            uninstallPackage(USER_0, CALLING_PACKAGE_2);
-            mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0, USER_0,
+            uninstallPackage(USER_10, CALLING_PACKAGE_2);
+            mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10,
                     /* appStillExists = */ false);
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_10)
                 .isEmpty();
     }
 
@@ -3798,35 +3799,35 @@
 
         setDefaultLauncherChecker((pkg, userId) -> {
             switch (userId) {
-                case USER_0:
+                case USER_10:
                     return LAUNCHER_2.equals(pkg);
                 case USER_P0:
                     return LAUNCHER_1.equals(pkg);
                 case USER_P1:
                     return LAUNCHER_1.equals(pkg);
-                case USER_10:
-                    return LAUNCHER_1.equals(pkg);
                 case USER_11:
                     return LAUNCHER_1.equals(pkg);
+                case USER_12:
+                    return LAUNCHER_1.equals(pkg);
                 default:
                     return false;
             }
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> mLauncherApps.registerCallback(c0_1, h));
-        runWithCaller(LAUNCHER_2, USER_0, () -> mLauncherApps.registerCallback(c0_2, h));
-        runWithCaller(LAUNCHER_3, USER_0, () -> mLauncherApps.registerCallback(c0_3, h));
-        runWithCaller(LAUNCHER_4, USER_0, () -> mLauncherApps.registerCallback(c0_4, h));
+        runWithCaller(LAUNCHER_1, USER_10, () -> mLauncherApps.registerCallback(c0_1, h));
+        runWithCaller(LAUNCHER_2, USER_10, () -> mLauncherApps.registerCallback(c0_2, h));
+        runWithCaller(LAUNCHER_3, USER_10, () -> mLauncherApps.registerCallback(c0_3, h));
+        runWithCaller(LAUNCHER_4, USER_10, () -> mLauncherApps.registerCallback(c0_4, h));
         runWithCaller(LAUNCHER_1, USER_P0, () -> mLauncherApps.registerCallback(cP0_1, h));
         runWithCaller(LAUNCHER_1, USER_P1, () -> mLauncherApps.registerCallback(cP1_1, h));
-        runWithCaller(LAUNCHER_1, USER_10, () -> mLauncherApps.registerCallback(c10_1, h));
-        runWithCaller(LAUNCHER_2, USER_10, () -> mLauncherApps.registerCallback(c10_2, h));
-        runWithCaller(LAUNCHER_1, USER_11, () -> mLauncherApps.registerCallback(c11_1, h));
+        runWithCaller(LAUNCHER_1, USER_11, () -> mLauncherApps.registerCallback(c10_1, h));
+        runWithCaller(LAUNCHER_2, USER_11, () -> mLauncherApps.registerCallback(c10_2, h));
+        runWithCaller(LAUNCHER_1, USER_12, () -> mLauncherApps.registerCallback(c11_1, h));
 
         // User 0.
 
         resetAll(all);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list());
         });
         waitOnMainThread();
@@ -3837,14 +3838,14 @@
         assertCallbackNotReceived(c10_1);
         assertCallbackNotReceived(c10_2);
         assertCallbackNotReceived(c11_1);
-        assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3");
-        assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
+        assertCallbackReceived(c0_2, HANDLE_USER_10, CALLING_PACKAGE_1, "s1", "s2", "s3");
+        assertCallbackReceived(cP0_1, HANDLE_USER_10, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
         assertCallbackNotReceived(cP1_1);
 
         // User 0, different package.
 
         resetAll(all);
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             mManager.removeDynamicShortcuts(list());
         });
         waitOnMainThread();
@@ -3855,8 +3856,8 @@
         assertCallbackNotReceived(c10_1);
         assertCallbackNotReceived(c10_2);
         assertCallbackNotReceived(c11_1);
-        assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4");
-        assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_3,
+        assertCallbackReceived(c0_2, HANDLE_USER_10, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4");
+        assertCallbackReceived(cP0_1, HANDLE_USER_10, CALLING_PACKAGE_3,
                 "s1", "s2", "s3", "s4", "s5", "s6");
         assertCallbackNotReceived(cP1_1);
 
@@ -3878,10 +3879,10 @@
         assertCallbackNotReceived(cP1_1);
 
         // Normal secondary user.
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         resetAll(all);
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             mManager.removeDynamicShortcuts(list());
         });
         waitOnMainThread();
@@ -3893,7 +3894,7 @@
         assertCallbackNotReceived(cP0_1);
         assertCallbackNotReceived(c10_2);
         assertCallbackNotReceived(c11_1);
-        assertCallbackReceived(c10_1, HANDLE_USER_10, CALLING_PACKAGE_1,
+        assertCallbackReceived(c10_1, HANDLE_USER_11, CALLING_PACKAGE_1,
                 "x1", "x2", "x3", "x4", "x5");
         assertCallbackNotReceived(cP1_1);
     }
@@ -3905,7 +3906,7 @@
 
         Log.i(TAG, "Saved state");
         dumpsysOnLogcat();
-        dumpUserFile(0);
+        dumpUserFile(USER_10);
 
         // Restore.
         mService.saveDirtyInfo();
@@ -3919,7 +3920,7 @@
      */
     public void SaveAndLoadUser() {
         // First, create some shortcuts and save.
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -3946,7 +3947,7 @@
             assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
             assertEquals(2, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -3974,9 +3975,9 @@
             assertEquals(2, mManager.getRemainingCallCount());
         });
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -4012,12 +4013,12 @@
         assertEquals(0, mService.getShortcutsForTest().size());
 
         // this will pre-load the per-user info.
-        mService.handleUnlockUser(UserHandle.USER_SYSTEM);
+        mService.handleUnlockUser(USER_10);
 
         // Now it's loaded.
         assertEquals(1, mService.getShortcutsForTest().size());
 
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4025,7 +4026,7 @@
             assertEquals("title1-1", getCallerShortcut("s1").getTitle());
             assertEquals("title1-2", getCallerShortcut("s2").getTitle());
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4035,12 +4036,12 @@
         });
 
         // Start another user
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
         // Now the size is 2.
         assertEquals(2, mService.getShortcutsForTest().size());
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4050,7 +4051,7 @@
         });
 
         // Try stopping the user
-        mService.handleStopUser(USER_10);
+        mService.handleStopUser(USER_11);
 
         // Now it's unloaded.
         assertEquals(1, mService.getShortcutsForTest().size());
@@ -4074,7 +4075,7 @@
 
     public void SaveCorruptAndLoadUser() throws Exception {
         // First, create some shortcuts and save.
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -4101,7 +4102,7 @@
             assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
             assertEquals(2, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -4129,9 +4130,9 @@
             assertEquals(2, mManager.getRemainingCallCount());
         });
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
             final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                     getTestContext().getResources(), R.drawable.icon2));
@@ -4162,14 +4163,14 @@
         // Save and corrupt the primary files.
         mService.saveDirtyInfo();
         try (Writer os = new FileWriter(
-                mService.getUserFile(UserHandle.USER_SYSTEM).getBaseFile())) {
+                mService.getUserFile(USER_10).getBaseFile())) {
             os.write("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
                     + "<user locales=\"en\" last-app-scan-time2=\"14400000");
         }
-        try (Writer os = new FileWriter(mService.getUserFile(USER_10).getBaseFile())) {
+        try (Writer os = new FileWriter(mService.getUserFile(USER_11).getBaseFile())) {
             os.write("<?xml version='1.0' encoding='utf");
         }
-        ShortcutPackage sp = mService.getUserShortcutsLocked(USER_0).getPackageShortcutsIfExists(
+        ShortcutPackage sp = mService.getUserShortcutsLocked(USER_10).getPackageShortcutsIfExists(
                 CALLING_PACKAGE_1);
         try (Writer os = new FileWriter(sp.getShortcutPackageItemFile().getPath())) {
             os.write("<?xml version='1.0' encoding='utf");
@@ -4182,12 +4183,12 @@
         assertEquals(0, mService.getShortcutsForTest().size());
 
         // this will pre-load the per-user info.
-        mService.handleUnlockUser(UserHandle.USER_SYSTEM);
+        mService.handleUnlockUser(USER_10);
 
         // Now it's loaded.
         assertEquals(1, mService.getShortcutsForTest().size());
 
-        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4195,7 +4196,7 @@
             assertEquals("title1-1", getCallerShortcut("s1").getTitle());
             assertEquals("title1-2", getCallerShortcut("s2").getTitle());
         });
-        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4205,12 +4206,12 @@
         });
 
         // Start another user
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
         // Now the size is 2.
         assertEquals(2, mService.getShortcutsForTest().size());
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
                     mManager.getDynamicShortcuts()))), "s1", "s2");
             assertEquals(2, mManager.getRemainingCallCount());
@@ -4220,7 +4221,7 @@
         });
 
         // Try stopping the user
-        mService.handleStopUser(USER_10);
+        mService.handleStopUser(USER_11);
 
         // Now it's unloaded.
         assertEquals(1, mService.getShortcutsForTest().size());
@@ -4229,72 +4230,72 @@
     }
 
     public void CleanupPackage() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s0_1"))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s0_2"))));
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
-                    HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
-                    HANDLE_USER_0);
-        });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
-                    HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
-                    HANDLE_USER_0);
-        });
-
-        mRunningUsers.put(USER_10, true);
-
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s10_1"))));
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(list(
-                    makeShortcut("s10_2"))));
-        });
         runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
                     HANDLE_USER_10);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
                     HANDLE_USER_10);
         });
         runWithCaller(LAUNCHER_2, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
                     HANDLE_USER_10);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
                     HANDLE_USER_10);
         });
 
+        mRunningUsers.put(USER_11, true);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s10_1"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s10_2"))));
+        });
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+                    HANDLE_USER_11);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+                    HANDLE_USER_11);
+        });
+        runWithCaller(LAUNCHER_2, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+                    HANDLE_USER_11);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+                    HANDLE_USER_11);
+        });
+
         // Remove all dynamic shortcuts; now all shortcuts are just pinned.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            mManager.removeAllDynamicShortcuts();
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            mManager.removeAllDynamicShortcuts();
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
         });
         runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
         });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            mManager.removeAllDynamicShortcuts();
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
+            mManager.removeAllDynamicShortcuts();
+        });
 
 
         final SparseArray<ShortcutUser> users = mService.getShortcutsForTest();
         assertEquals(2, users.size());
-        assertEquals(USER_0, users.keyAt(0));
-        assertEquals(USER_10, users.keyAt(1));
+        assertEquals(USER_10, users.keyAt(0));
+        assertEquals(USER_11, users.keyAt(1));
 
-        final ShortcutUser user0 = users.get(USER_0);
-        final ShortcutUser user10 = users.get(USER_10);
+        final ShortcutUser user0 = users.get(USER_10);
+        final ShortcutUser user10 = users.get(USER_11);
 
 
         // Check the registered packages.
@@ -4304,31 +4305,31 @@
         assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 hashSet(user10.getAllPackagesForTest().keySet()));
         assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
                 set(UserPackage.of(USER_10, LAUNCHER_1),
                         UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_11, LAUNCHER_1),
+                        UserPackage.of(USER_11, LAUNCHER_2)),
                 hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_1", "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
-                "s10_1", "s10_2");
+                "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_1", "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_11),
                 "s10_1", "s10_2");
-        assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_11),
+                "s10_1", "s10_2");
+        assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_11);
 
         mService.saveDirtyInfo();
 
         // Nonexistent package.
-        uninstallPackage(USER_0, "abc");
-        mService.cleanUpPackageLocked("abc", USER_0, USER_0, /* appStillExists = */ false);
+        uninstallPackage(USER_10, "abc");
+        mService.cleanUpPackageLocked("abc", USER_10, USER_10, /* appStillExists = */ false);
 
         // No changes.
         assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
@@ -4336,171 +4337,171 @@
         assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 hashSet(user10.getAllPackagesForTest().keySet()));
         assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
                 set(UserPackage.of(USER_10, LAUNCHER_1),
                         UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_11, LAUNCHER_1),
+                        UserPackage.of(USER_11, LAUNCHER_2)),
                 hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_1", "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
-                "s10_1", "s10_2");
+                "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_1", "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_11),
                 "s10_1", "s10_2");
-        assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_11),
+                "s10_1", "s10_2");
+        assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_11);
 
         mService.saveDirtyInfo();
 
         // Remove a package.
-        uninstallPackage(USER_0, CALLING_PACKAGE_1);
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0,
-                /* appStillExists = */ false);
-
-        assertEquals(set(CALLING_PACKAGE_2),
-                hashSet(user0.getAllPackagesForTest().keySet()));
-        assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                hashSet(user10.getAllPackagesForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_10, LAUNCHER_1),
-                        UserPackage.of(USER_10, LAUNCHER_2)),
-                hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
-                "s10_1", "s10_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
-                "s10_1", "s10_2");
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
-
-        mService.saveDirtyInfo();
-
-        // Remove a launcher.
-        uninstallPackage(USER_10, LAUNCHER_1);
-        mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10, /* appStillExists = */ false);
-
-        assertEquals(set(CALLING_PACKAGE_2),
-                hashSet(user0.getAllPackagesForTest().keySet()));
-        assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
-                hashSet(user10.getAllPackagesForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_10, LAUNCHER_2)),
-                hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
-                "s10_1", "s10_2");
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
-
-        mService.saveDirtyInfo();
-
-        // Remove a package.
-        uninstallPackage(USER_10, CALLING_PACKAGE_2);
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10,
-                /* appStillExists = */ false);
-
-        assertEquals(set(CALLING_PACKAGE_2),
-                hashSet(user0.getAllPackagesForTest().keySet()));
-        assertEquals(set(CALLING_PACKAGE_1),
-                hashSet(user10.getAllPackagesForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_10, LAUNCHER_2)),
-                hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
-                "s10_1");
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
-
-        mService.saveDirtyInfo();
-
-        // Remove the other launcher from user 10 too.
-        uninstallPackage(USER_10, LAUNCHER_2);
-        mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10,
-                /* appStillExists = */ false);
-
-        assertEquals(set(CALLING_PACKAGE_2),
-                hashSet(user0.getAllPackagesForTest().keySet()));
-        assertEquals(set(CALLING_PACKAGE_1),
-                hashSet(user10.getAllPackagesForTest().keySet()));
-        assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
-                hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(
-                set(),
-                hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
-                "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
-                "s0_2");
-
-        // Note the pinned shortcuts on user-10 no longer referred, so they should both be removed.
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
-
-        mService.saveDirtyInfo();
-
-        // More remove.
         uninstallPackage(USER_10, CALLING_PACKAGE_1);
         mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10,
                 /* appStillExists = */ false);
 
         assertEquals(set(CALLING_PACKAGE_2),
                 hashSet(user0.getAllPackagesForTest().keySet()));
-        assertEquals(set(),
+        assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 hashSet(user10.getAllPackagesForTest().keySet()));
         assertEquals(
-                set(UserPackage.of(USER_0, LAUNCHER_1),
-                        UserPackage.of(USER_0, LAUNCHER_2)),
+                set(UserPackage.of(USER_10, LAUNCHER_1),
+                        UserPackage.of(USER_10, LAUNCHER_2)),
                 hashSet(user0.getAllLaunchersForTest().keySet()));
-        assertEquals(set(),
+        assertEquals(
+                set(UserPackage.of(USER_11, LAUNCHER_1),
+                        UserPackage.of(USER_11, LAUNCHER_2)),
                 hashSet(user10.getAllLaunchersForTest().keySet()));
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
                 "s0_2");
-        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_11),
+                "s10_1", "s10_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_11),
+                "s10_1", "s10_2");
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_11);
+
+        mService.saveDirtyInfo();
+
+        // Remove a launcher.
+        uninstallPackage(USER_11, LAUNCHER_1);
+        mService.cleanUpPackageLocked(LAUNCHER_1, USER_11, USER_11, /* appStillExists = */ false);
+
+        assertEquals(set(CALLING_PACKAGE_2),
+                hashSet(user0.getAllPackagesForTest().keySet()));
+        assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+                hashSet(user10.getAllPackagesForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_10, LAUNCHER_1),
+                        UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_11, LAUNCHER_2)),
+                hashSet(user10.getAllLaunchersForTest().keySet()));
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_11),
+                "s10_1", "s10_2");
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_11);
+
+        mService.saveDirtyInfo();
+
+        // Remove a package.
+        uninstallPackage(USER_11, CALLING_PACKAGE_2);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_11, USER_11,
+                /* appStillExists = */ false);
+
+        assertEquals(set(CALLING_PACKAGE_2),
+                hashSet(user0.getAllPackagesForTest().keySet()));
+        assertEquals(set(CALLING_PACKAGE_1),
+                hashSet(user10.getAllPackagesForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_10, LAUNCHER_1),
+                        UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_11, LAUNCHER_2)),
+                hashSet(user10.getAllLaunchersForTest().keySet()));
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_11),
+                "s10_1");
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_11);
+
+        mService.saveDirtyInfo();
+
+        // Remove the other launcher from user 10 too.
+        uninstallPackage(USER_11, LAUNCHER_2);
+        mService.cleanUpPackageLocked(LAUNCHER_2, USER_11, USER_11,
+                /* appStillExists = */ false);
+
+        assertEquals(set(CALLING_PACKAGE_2),
+                hashSet(user0.getAllPackagesForTest().keySet()));
+        assertEquals(set(CALLING_PACKAGE_1),
+                hashSet(user10.getAllPackagesForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_10, LAUNCHER_1),
+                        UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(
+                set(),
+                hashSet(user10.getAllLaunchersForTest().keySet()));
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
                 "s0_2");
 
         // Note the pinned shortcuts on user-10 no longer referred, so they should both be removed.
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
-        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
-        assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_10);
-        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_11);
+
+        mService.saveDirtyInfo();
+
+        // More remove.
+        uninstallPackage(USER_11, CALLING_PACKAGE_1);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_11, USER_11,
+                /* appStillExists = */ false);
+
+        assertEquals(set(CALLING_PACKAGE_2),
+                hashSet(user0.getAllPackagesForTest().keySet()));
+        assertEquals(set(),
+                hashSet(user10.getAllPackagesForTest().keySet()));
+        assertEquals(
+                set(UserPackage.of(USER_10, LAUNCHER_1),
+                        UserPackage.of(USER_10, LAUNCHER_2)),
+                hashSet(user0.getAllLaunchersForTest().keySet()));
+        assertEquals(set(),
+                hashSet(user10.getAllLaunchersForTest().keySet()));
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+                "s0_2");
+        assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+                "s0_2");
+
+        // Note the pinned shortcuts on user-10 no longer referred, so they should both be removed.
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_10);
+        assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_10);
+        assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_11);
+        assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_11);
 
         mService.saveDirtyInfo();
     }
@@ -4511,15 +4512,15 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s2", "s3", "ms1", "ms2"), HANDLE_USER_0);
+                    list("s2", "s3", "ms1", "ms2"), HANDLE_USER_10);
         });
 
         // Remove ms2 from manifest.
@@ -4528,9 +4529,9 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
 
@@ -4564,9 +4565,9 @@
         });
 
         // Clean up + re-publish manifests.
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0,
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10,
                 /* appStillExists = */ true);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1")
                     .areAllManifest();
@@ -4575,7 +4576,7 @@
 
     public void HandleGonePackage_crossProfile() {
         // Create some shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
@@ -4583,253 +4584,253 @@
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         // Pin some.
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s1"), HANDLE_USER_0);
+                    list("s1"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s2"), UserHandle.of(USER_P0));
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s3"), HANDLE_USER_0);
+                    list("s3"), HANDLE_USER_10);
         });
 
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s2"), HANDLE_USER_0);
+                    list("s2"), HANDLE_USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s3"), UserHandle.of(USER_P0));
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    list("s1"), HANDLE_USER_0);
+                    list("s1"), HANDLE_USER_10);
         });
 
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("s3"), HANDLE_USER_10);
+                    list("s3"), HANDLE_USER_11);
         });
 
         // Check the state.
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         // Make sure all the information is persisted.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
-        mService.handleUnlockUser(USER_P0);
         mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_11);
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         // Start uninstalling.
-        uninstallPackage(USER_10, LAUNCHER_1);
-        mService.checkPackageChanges(USER_10);
+        uninstallPackage(USER_11, LAUNCHER_1);
+        mService.checkPackageChanges(USER_11);
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
+
+        // Uninstall.
+        uninstallPackage(USER_11, CALLING_PACKAGE_1);
+        mService.checkPackageChanges(USER_11);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
+
+        uninstallPackage(USER_P0, LAUNCHER_1);
+        mService.checkPackageChanges(USER_10);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
-        // Uninstall.
-        uninstallPackage(USER_10, CALLING_PACKAGE_1);
-        mService.checkPackageChanges(USER_10);
-
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
-
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
-
-        uninstallPackage(USER_P0, LAUNCHER_1);
-        mService.checkPackageChanges(USER_0);
-
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
-
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
-
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         mService.checkPackageChanges(USER_P0);
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         uninstallPackage(USER_P0, CALLING_PACKAGE_1);
 
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
-        mService.handleUnlockUser(USER_P0);
         mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_11);
 
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
         // Uninstall
-        uninstallPackage(USER_0, LAUNCHER_1);
+        uninstallPackage(USER_10, LAUNCHER_1);
 
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
-        mService.handleUnlockUser(USER_P0);
         mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_11);
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
 
-        uninstallPackage(USER_0, CALLING_PACKAGE_2);
+        uninstallPackage(USER_10, CALLING_PACKAGE_2);
 
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_0);
-        mService.handleUnlockUser(USER_P0);
         mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_11);
 
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
-        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
 
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
         assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_10));
 
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
-        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_11));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_11));
     }
 
     protected void checkCanRestoreTo(int expected, ShortcutPackageInfo spi,
@@ -4854,11 +4855,11 @@
                 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
 
         final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackageForTest(
-                mService, CALLING_PACKAGE_1, USER_0);
+                mService, CALLING_PACKAGE_1, USER_10);
         final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackageForTest(
-                mService, CALLING_PACKAGE_2, USER_0);
+                mService, CALLING_PACKAGE_2, USER_10);
         final ShortcutPackageInfo spi3 = ShortcutPackageInfo.generateForInstalledPackageForTest(
-                mService, CALLING_PACKAGE_3, USER_0);
+                mService, CALLING_PACKAGE_3, USER_10);
 
         checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "sig1");
         checkCanRestoreTo(DISABLED_REASON_NOT_DISABLED, spi1, false, 10, true, "x", "sig1");
@@ -4927,7 +4928,7 @@
     private void checkHandlePackageDeleteInner(BiConsumer<Integer, String> remover) {
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(
                 makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
         )));
@@ -4937,8 +4938,8 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1", "s2", "ms1")
 
@@ -4946,187 +4947,187 @@
                     .haveIds("ms1");
         });
 
-        setCaller(CALLING_PACKAGE_2, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
-        setCaller(CALLING_PACKAGE_3, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
-        mRunningUsers.put(USER_10, true);
-
-        setCaller(CALLING_PACKAGE_1, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
         setCaller(CALLING_PACKAGE_2, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
+        mRunningUsers.put(USER_11, true);
+
+        setCaller(CALLING_PACKAGE_1, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
+        setCaller(CALLING_PACKAGE_2, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
+        setCaller(CALLING_PACKAGE_3, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
 
-        remover.accept(USER_0, CALLING_PACKAGE_1);
+        remover.accept(USER_10, CALLING_PACKAGE_1);
 
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        remover.accept(USER_10, CALLING_PACKAGE_2);
+        remover.accept(USER_11, CALLING_PACKAGE_2);
 
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
 
         mInjectedPackages.remove(CALLING_PACKAGE_1);
         mInjectedPackages.remove(CALLING_PACKAGE_3);
 
-        mService.checkPackageChanges(USER_0);
-
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));  // ---------------
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
-
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
-
         mService.checkPackageChanges(USER_10);
 
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
         assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));  // ---------------
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
         assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
+
+        mService.checkPackageChanges(USER_11);
+
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
+
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
     }
 
     /** Almost ame as testHandlePackageDelete, except it doesn't uninstall packages. */
     public void HandlePackageClearData() {
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(
                 makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
         )));
 
-        setCaller(CALLING_PACKAGE_2, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
-        setCaller(CALLING_PACKAGE_3, USER_0);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
-        mRunningUsers.put(USER_10, true);
-
-        setCaller(CALLING_PACKAGE_1, USER_10);
-        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
-
         setCaller(CALLING_PACKAGE_2, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
         setCaller(CALLING_PACKAGE_3, USER_10);
         assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
 
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
+        mRunningUsers.put(USER_11, true);
+
+        setCaller(CALLING_PACKAGE_1, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
+        setCaller(CALLING_PACKAGE_2, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
+        setCaller(CALLING_PACKAGE_3, USER_11);
+        assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
+
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
 
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageDataClear(CALLING_PACKAGE_1, USER_0));
+                genPackageDataClear(CALLING_PACKAGE_1, USER_10));
 
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageDataClear(CALLING_PACKAGE_2, USER_10));
+                genPackageDataClear(CALLING_PACKAGE_2, USER_11));
 
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_0));
-        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
         assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_11));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_11));
+        assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_11));
 
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
-        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
-        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
         assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_11));
+        assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_11));
+        assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_11));
     }
 
     public void HandlePackageClearData_manifestRepublished() {
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         // Add two manifests and two dynamics.
         addManifestShortcutResource(
@@ -5134,17 +5135,17 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_11);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "s1", "s2")
                     .areAllEnabled()
@@ -5155,10 +5156,10 @@
 
         // Clear data
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageDataClear(CALLING_PACKAGE_1, USER_10));
+                genPackageDataClear(CALLING_PACKAGE_1, USER_11));
 
         // Only manifest shortcuts will remain, and are no longer pinned.
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2")
                     .areAllEnabled()
@@ -5173,31 +5174,31 @@
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcutWithIcon("s2", res32x32),
                     makeShortcutWithIcon("s3", res32x32),
                     makeShortcutWithIcon("s4", bmp32x32))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcutWithIcon("s2", bmp32x32))));
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("s1", res32x32))));
         });
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("s1", res32x32),
                     makeShortcutWithIcon("s2", res32x32))));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("s1", bmp32x32),
                     makeShortcutWithIcon("s2", bmp32x32))));
@@ -5206,10 +5207,10 @@
         LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
         LauncherApps.Callback c10 = mock(LauncherApps.Callback.class);
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerCallback(c0, new Handler(Looper.getMainLooper()));
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
             mLauncherApps.registerCallback(c10, new Handler(Looper.getMainLooper()));
         });
 
@@ -5224,7 +5225,7 @@
 
         // Then send the broadcast, to only user-0.
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
 
         waitOnMainThread();
 
@@ -5233,7 +5234,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(HANDLE_USER_0));
+                eq(HANDLE_USER_10));
 
         // User-10 shouldn't yet get the notification.
         verify(c10, times(0)).onShortcutsChanged(
@@ -5254,14 +5255,14 @@
         // notification to the launcher.
         mInjectedCurrentTimeMillis = START_TIME + 200;
 
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
 
         reset(c0);
         reset(c10);
         setPackageLastUpdateTime(CALLING_PACKAGE_1, mInjectedCurrentTimeMillis);
-        mService.handleUnlockUser(USER_10);
-        mService.checkPackageChanges(USER_10);
+        mService.handleUnlockUser(USER_11);
+        mService.checkPackageChanges(USER_11);
 
         waitOnMainThread();
 
@@ -5274,7 +5275,7 @@
         verify(c10).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(HANDLE_USER_10));
+                eq(HANDLE_USER_11));
 
         assertShortcutIds(shortcuts.getValue(), "s1", "s2");
         assertEquals(START_TIME + 200,
@@ -5292,7 +5293,7 @@
 
         // Then send the broadcast, to only user-0.
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
+                genPackageUpdateIntent(CALLING_PACKAGE_2, USER_10));
 
         waitOnMainThread();
 
@@ -5315,8 +5316,8 @@
 
         // Then send the broadcast, to only user-0.
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
-        mService.checkPackageChanges(USER_10);
+                genPackageUpdateIntent(CALLING_PACKAGE_3, USER_10));
+        mService.checkPackageChanges(USER_11);
 
         waitOnMainThread();
 
@@ -5324,7 +5325,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_3),
                 shortcuts.capture(),
-                eq(HANDLE_USER_0));
+                eq(HANDLE_USER_10));
 
         // User 10 doesn't have package 3, so no callback.
         verify(c10, times(0)).onShortcutsChanged(
@@ -5345,7 +5346,7 @@
         final Icon icon2 = Icon.createWithResource(getTestContext(), /* res ID */ 1001);
 
         // Set up shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // Note resource strings are not officially supported (they're hidden), but
             // should work.
 
@@ -5371,7 +5372,7 @@
         });
 
         // Verify.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ShortcutInfo s1 = getCallerShortcut("s1");
             final ShortcutInfo s2 = getCallerShortcut("s2");
 
@@ -5397,9 +5398,9 @@
         // Update the package.
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ShortcutInfo s1 = getCallerShortcut("s1");
             final ShortcutInfo s2 = getCallerShortcut("s2");
 
@@ -5422,20 +5423,20 @@
         mSystemPackages.add(CALLING_PACKAGE_1);
 
         // Initial state: no shortcuts.
-        mService.checkPackageChanges(USER_0);
+        mService.checkPackageChanges(USER_10);
 
         assertEquals(mInjectedCurrentTimeMillis,
-                mService.getUserShortcutsLocked(USER_0).getLastAppScanTime());
+                mService.getUserShortcutsLocked(USER_10).getLastAppScanTime());
         assertEquals(mInjectedBuildFingerprint,
-                mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint());
+                mService.getUserShortcutsLocked(USER_10).getLastAppScanOsFingerprint());
 
         // They have no shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .isEmpty();
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .isEmpty();
         });
@@ -5451,13 +5452,13 @@
                 new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
                 R.xml.shortcut_1);
         mInjectedCurrentTimeMillis += 1000;
-        mService.checkPackageChanges(USER_0);
+        mService.checkPackageChanges(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .isEmpty();
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .isEmpty();
         });
@@ -5466,13 +5467,13 @@
         // Update the build finger print.  All apps will be scanned now.
         mInjectedBuildFingerprint = "update1";
         mInjectedCurrentTimeMillis += 1000;
-        mService.checkPackageChanges(USER_0);
+        mService.checkPackageChanges(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1");
         });
@@ -5486,14 +5487,14 @@
                 new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
                 R.xml.shortcut_2);
         mInjectedCurrentTimeMillis += 1000;
-        mService.checkPackageChanges(USER_0);
+        mService.checkPackageChanges(USER_10);
 
         // Fingerprint hasn't changed, so there packages weren't scanned.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1");
         });
@@ -5502,13 +5503,13 @@
         // all apps anyway.
         mInjectedBuildFingerprint = "update2";
         mInjectedCurrentTimeMillis += 1000;
-        mService.checkPackageChanges(USER_0);
+        mService.checkPackageChanges(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2");
         });
@@ -5516,9 +5517,9 @@
         // Make sure getLastAppScanTime / getLastAppScanOsFingerprint are persisted.
         initService();
         assertEquals(mInjectedCurrentTimeMillis,
-                mService.getUserShortcutsLocked(USER_0).getLastAppScanTime());
+                mService.getUserShortcutsLocked(USER_10).getLastAppScanTime());
         assertEquals(mInjectedBuildFingerprint,
-                mService.getUserShortcutsLocked(USER_0).getLastAppScanOsFingerprint());
+                mService.getUserShortcutsLocked(USER_10).getLastAppScanOsFingerprint());
     }
 
     public void HandlePackageChanged() {
@@ -5528,23 +5529,23 @@
         addManifestShortcutResource(ACTIVITY1, R.xml.shortcut_1);
         addManifestShortcutResource(ACTIVITY2, R.xml.shortcut_1_alt);
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(
                     makeShortcutWithActivity("s1", ACTIVITY1),
                     makeShortcutWithActivity("s2", ACTIVITY2)
             )));
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1-alt", "s2"), HANDLE_USER_10);
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1-alt", "s2"), HANDLE_USER_11);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms1-alt", "s1", "s2")
                     .areAllEnabled()
@@ -5564,9 +5565,9 @@
 
         // First, no changes.
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageChangedIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms1-alt", "s1", "s2")
                     .areAllEnabled()
@@ -5587,9 +5588,9 @@
         // Disable activity 1
         mEnabledActivityChecker = (activity, userId) -> !ACTIVITY1.equals(activity);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageChangedIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1-alt", "s2")
                     .areAllEnabled()
@@ -5607,9 +5608,9 @@
         // Manifest shortcuts will be re-published, but dynamic ones are not.
         mEnabledActivityChecker = (activity, userId) -> true;
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageChangedIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms1-alt", "s2")
                     .areAllEnabled()
@@ -5631,9 +5632,9 @@
         // Because "ms1-alt" and "s2" are both pinned, they will remain, but disabled.
         mEnabledActivityChecker = (activity, userId) -> !ACTIVITY2.equals(activity);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageChangedIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms1-alt", "s2")
 
@@ -5652,7 +5653,7 @@
     }
 
     public void HandlePackageUpdate_activityNoLongerMain() throws Throwable {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithActivity("s1a",
                             new ComponentName(getCallingPackage(), "act1")),
@@ -5671,12 +5672,12 @@
                     .haveIds("s1a", "s1b", "s2a", "s2b", "s3a", "s3b")
                     .areAllDynamic();
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("s1b", "s2b", "s3b"),
-                    HANDLE_USER_0);
+                    HANDLE_USER_10);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1a", "s1b", "s2a", "s2b", "s3a", "s3b")
                     .areAllDynamic()
@@ -5690,17 +5691,17 @@
             return activity.getClassName().equals("act1");
         };
 
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
         assertForLauncherCallback(mLauncherApps, () -> {
             updatePackageVersion(CALLING_PACKAGE_1, 1);
             mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+                    genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 // Make sure the launcher gets callbacks.
                 .haveIds("s1a", "s1b", "s2b", "s3b")
                 .areAllWithKeyFieldsOnly();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // s2a and s3a are gone, but s2b and s3b will remain because they're pinned, and
             // disabled.
             assertWith(getCallerShortcuts())
@@ -5800,24 +5801,24 @@
         assertEquals(0, userP0.getAllLaunchersForTest().size());
 
         // Make sure only "allowBackup" apps are restored, and are shadow.
-        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_10);
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
 
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
         assertExistsAndShadow(user0.getAllLaunchersForTest().get(
-                UserPackage.of(USER_0, LAUNCHER_1)));
+                UserPackage.of(USER_10, LAUNCHER_1)));
         assertExistsAndShadow(user0.getAllLaunchersForTest().get(
-                UserPackage.of(USER_0, LAUNCHER_2)));
+                UserPackage.of(USER_10, LAUNCHER_2)));
 
-        assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_0, LAUNCHER_3)));
+        assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_10, LAUNCHER_3)));
         assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_P0, LAUNCHER_1)));
 
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
                 anyString());
 
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .selectDynamic()
                     .isEmpty()
@@ -5828,25 +5829,25 @@
                     .areAllEnabled();
         });
 
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s1")
                     .areAllEnabled();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .isEmpty();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
 
             assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
                     .isEmpty();
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_2);
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .selectDynamic()
                     .isEmpty()
@@ -5857,18 +5858,18 @@
                     .areAllEnabled();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s1")
                     .areAllEnabled();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s1", "s2")
                     .areAllEnabled();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
 
             assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
@@ -5876,19 +5877,19 @@
         });
 
         // 3 shouldn't be backed up, so no pinned shortcuts.
-        installPackage(USER_0, CALLING_PACKAGE_3);
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .isEmpty();
         });
 
         // Launcher on a different profile shouldn't be restored.
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .isEmpty();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .isEmpty();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
         });
 
@@ -5900,21 +5901,21 @@
         });
 
         // Restore launcher 2 on user 0.
-        installPackage(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2")
                     .areAllEnabled();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2", "s3")
                     .areAllEnabled();
 
             if (firstRestore) {
                 assertWith(
-                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                         .haveIds("s2", "s3", "s4")
                         .areAllDisabled()
                         .areAllPinned()
@@ -5923,7 +5924,7 @@
                                 ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
             } else {
                 assertWith(
-                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                         .isEmpty();
             }
 
@@ -5934,28 +5935,28 @@
 
         // Restoration of launcher2 shouldn't affect other packages; so do the same checks and
         // make sure they still have the same result.
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .areAllPinned()
                     .haveIds("s1", "s2");
         });
 
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s1")
                     .areAllEnabled();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s1", "s2")
                     .areAllEnabled();
 
             if (firstRestore) {
                 assertWith(
-                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                         .haveIds("s1", "s2", "s3")
                         .areAllDisabled()
                         .areAllPinned()
@@ -5963,7 +5964,7 @@
                         .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
             } else {
                 assertWith(
-                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                        mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                         .isEmpty();
             }
 
@@ -5971,8 +5972,8 @@
                     .isEmpty();
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_2);
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .areAllPinned()
                     .haveIds("s1", "s2", "s3")
@@ -6004,30 +6005,30 @@
                 mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
                 eq(CALLING_PACKAGE_1));
 
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
-        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_10)
                 .getPackageInfo().isShadow());
 
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
                 any(byte[].class), anyString());
 
-        installPackage(USER_0, CALLING_PACKAGE_2);
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3");
         });
-        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, USER_0)
+        assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, USER_10)
                 .getPackageInfo().isShadow());
 
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .haveIds("s1")
                     .areAllPinned()
                     .areAllDisabled()
@@ -6055,61 +6056,61 @@
                                 fail("Unhandled disabled reason: " + package1DisabledReason);
                         }
                     });
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .haveIds("s1", "s2")
                     .areAllPinned()
                     .areAllEnabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
         });
-        installPackage(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .haveIds("s2")
                     .areAllPinned()
                     .areAllDisabled()
                     .areAllWithDisabledReason(package1DisabledReason);
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .haveIds("s2", "s3")
                     .areAllPinned()
                     .areAllEnabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_3);
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .haveIds("s1")
                     .areAllPinned()
                     .areAllDisabled()
                     .areAllWithDisabledReason(package1DisabledReason);
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .haveIds("s1", "s2")
                     .areAllPinned()
                     .areAllEnabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .haveIds("s1", "s2", "s3")
                     .areAllPinned()
                     .areAllDisabled()
                     .areAllWithDisabledReason(ShortcutInfo.DISABLED_REASON_BACKUP_NOT_SUPPORTED);
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .haveIds("s2")
                     .areAllPinned()
                     .areAllDisabled()
                     .areAllWithDisabledReason(package1DisabledReason);
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .haveIds("s2", "s3")
                     .areAllPinned()
                     .areAllEnabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .haveIds("s2", "s3", "s4")
                     .areAllPinned()
                     .areAllDisabled()
@@ -6147,8 +6148,8 @@
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
                 any(byte[].class), anyString());
 
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
 
             // s1 was pinned by launcher 1, which is not restored, yet, so we still see "s1" here.
@@ -6157,8 +6158,8 @@
                     "s1", "s2");
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_2);
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
@@ -6170,22 +6171,22 @@
 
         // Now we try to restore launcher 1.  Then we realize it's not restorable, so L1 has no pinned
         // shortcuts.
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     /* empty */);
         });
-        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_10)
                 .getPackageInfo().isShadow());
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
 
             // Now CALLING_PACKAGE_1 realizes "s1" is no longer pinned.
@@ -6197,44 +6198,44 @@
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
                 any(byte[].class), anyString());
 
-        installPackage(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        installPackage(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10)),
                     "s2");
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10)),
                     "s2", "s3");
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     /* empty */);
         });
-        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_2, USER_0)
+        assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_2, USER_10)
                 .getPackageInfo().isShadow());
 
-        installPackage(USER_0, CALLING_PACKAGE_3);
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     /* empty */);
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10)),
                     "s2");
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10)),
                     "s2", "s3");
         });
     }
@@ -6254,80 +6255,80 @@
     protected void checkBackupAndRestore_publisherAndLauncherNotRestored() {
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
                 anyString());
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_2);
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_2);
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3");
         });
 
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     /* empty */);
         });
-        installPackage(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        installPackage(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2")
                     .areAllDisabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2", "s3");
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
         });
 
         // Because launcher 1 wasn't restored, "s1" is no longer pinned.
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s2", "s3");
         });
 
-        installPackage(USER_0, CALLING_PACKAGE_3);
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_3);
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEquals(0, mManager.getDynamicShortcuts().size());
             assertEquals(0, mManager.getPinnedShortcuts().size());
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     /* empty */);
             assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     /* empty */);
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2")
                     .areAllDisabled();
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .areAllPinned()
                     .haveIds("s2", "s3");
             assertWith(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .haveIds("s2", "s3", "s4")
                     .areAllDisabled()
                     .areAllPinned()
@@ -6341,7 +6342,7 @@
         prepareCrossProfileDataSet();
 
         // Before doing backup & restore, disable s1.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.disableShortcuts(list("s1"));
         });
 
@@ -6355,23 +6356,23 @@
         assertEquals(0, userP0.getAllLaunchersForTest().size());
 
         // Make sure only "allowBackup" apps are restored, and are shadow.
-        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_10);
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
         assertExistsAndShadow(user0.getAllLaunchersForTest().get(
-                UserPackage.of(USER_0, LAUNCHER_1)));
+                UserPackage.of(USER_10, LAUNCHER_1)));
         assertExistsAndShadow(user0.getAllLaunchersForTest().get(
-                UserPackage.of(USER_0, LAUNCHER_2)));
+                UserPackage.of(USER_10, LAUNCHER_2)));
 
-        assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_0, LAUNCHER_3)));
+        assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_10, LAUNCHER_3)));
         assertNull(user0.getAllLaunchersForTest().get(UserPackage.of(USER_P0, LAUNCHER_1)));
 
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(any(byte[].class),
                 anyString());
 
-        installPackage(USER_0, CALLING_PACKAGE_1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        installPackage(USER_10, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .areAllEnabled() // disabled shortcuts shouldn't be restored.
 
@@ -6384,16 +6385,16 @@
                     .haveIds("s2");
         });
 
-        installPackage(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        installPackage(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Note, s1 was pinned by launcher 1, but was disabled, so isn't restored.
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10))
                     .isEmpty();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_10))
                     .isEmpty();
 
-            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_10))
                     .isEmpty();
 
             assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
@@ -6409,17 +6410,17 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
         // Pin from launcher 1.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_0);
+                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_10);
         });
 
         // Update and now ms2 is gone -> disabled.
@@ -6428,10 +6429,10 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Make sure the manifest shortcuts have been published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .selectManifest()
                     .haveIds("ms1")
@@ -6461,11 +6462,11 @@
 
         // When re-installing the app, the manifest shortcut should be re-published.
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(LAUNCHER_1, USER_0));
+                genPackageAddIntent(LAUNCHER_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .selectPinned()
                     // ms2 was disabled, so not restored.
@@ -6502,17 +6503,17 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
         // Pin from launcher 1.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_0);
+                    list("ms1", "ms2", "s1", "s2"), HANDLE_USER_10);
         });
 
         // Update and now ms2 is gone -> disabled.
@@ -6521,7 +6522,7 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Set up shortcuts for package 3, which won't be backed up / restored.
         addManifestShortcutResource(
@@ -6529,15 +6530,15 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_3, 1);
         mService.mPackageMonitor.onReceive(mServiceContext,
-                genPackageAddIntent(CALLING_PACKAGE_3, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_3, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertTrue(getManager().setDynamicShortcuts(list(
                     makeShortcut("s1"))));
         });
 
         // Make sure the manifest shortcuts have been published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .selectManifest()
                     .haveIds("ms1")
@@ -6561,7 +6562,7 @@
                     .areAllDisabled();
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1", "ms1");
         });
@@ -6575,7 +6576,7 @@
 
             dumpsysOnLogcat("Before backup");
 
-            final byte[] payload = mService.getBackupPayload(USER_0);
+            final byte[] payload = mService.getBackupPayload(USER_10);
             if (ENABLE_DUMP) {
                 final String xml = new String(payload);
                 Log.v(TAG, "Backup payload:");
@@ -6583,7 +6584,7 @@
                     Log.v(TAG, line);
                 }
             }
-            mService.applyRestore(payload, USER_0);
+            mService.applyRestore(payload, USER_10);
 
             dumpsysOnLogcat("After restore");
 
@@ -6591,7 +6592,7 @@
         }
 
         // The check is also the same as testBackupAndRestore_manifestRePublished().
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerVisibleShortcuts())
                     .selectPinned()
                     // ms2 was disabled, so not restored.
@@ -6609,7 +6610,7 @@
         });
 
         // Package 3 still has the same shortcuts.
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1", "ms1");
         });
@@ -6627,31 +6628,31 @@
         doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(
                 any(byte[].class), anyString());
 
-        runWithSystemUid(() -> mService.applyRestore(payload, USER_0));
+        runWithSystemUid(() -> mService.applyRestore(payload, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .areAllPinned()
                     .haveIds("s1")
                     .areAllEnabled();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(getShortcutAsLauncher(USER_0))
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(getShortcutAsLauncher(USER_10))
                     .areAllPinned()
                     .haveIds("s1")
                     .areAllEnabled();
         });
         // Make sure getBackupSourceVersionCode and isBackupSourceBackupAllowed
         // are correct. We didn't have them in the old format.
-        assertEquals(8, mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+        assertEquals(8, mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_10)
                 .getPackageInfo().getBackupSourceVersionCode());
-        assertTrue(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+        assertTrue(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_10)
                 .getPackageInfo().isBackupSourceBackupAllowed());
 
-        assertEquals(9, mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+        assertEquals(9, mService.getLauncherShortcutForTest(LAUNCHER_1, USER_10)
                 .getPackageInfo().getBackupSourceVersionCode());
-        assertTrue(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+        assertTrue(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_10)
                 .getPackageInfo().isBackupSourceBackupAllowed());
 
     }
@@ -6664,25 +6665,25 @@
         mService.saveDirtyInfo();
         initService();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3", "s4");
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3", "s4", "s5");
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
                     "s1", "s2", "s3");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
                     "s1", "s2", "s3", "s4", "s5", "s6");
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts())
                     /* empty */);
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts())
@@ -6700,24 +6701,24 @@
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts())
                     /* empty */);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()),
                     "x1", "x2", "x3");
             assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()),
                     "x4", "x5");
         });
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
                     "s1");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10),
                     "s1", "s2");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10),
                     "s1", "s2", "s3");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
@@ -6728,21 +6729,21 @@
             assertExpectException(
                     SecurityException.class, "", () -> {
                         mLauncherApps.getShortcuts(
-                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_11);
                     });
         });
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
                     "s2");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10),
                     "s2", "s3");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10),
                     "s2", "s3", "s4");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
@@ -6751,18 +6752,18 @@
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
                     /* empty */);
         });
-        runWithCaller(LAUNCHER_3, USER_0, () -> {
+        runWithCaller(LAUNCHER_3, USER_10, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
                     "s3");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10),
                     "s3", "s4");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10),
                     "s3", "s4", "s5");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
@@ -6771,18 +6772,18 @@
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_P0)
                     /* empty */);
         });
-        runWithCaller(LAUNCHER_4, USER_0, () -> {
+        runWithCaller(LAUNCHER_4, USER_10, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_0)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_4), HANDLE_USER_10)
                     /* empty */);
             assertShortcutIds(
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0)
@@ -6793,13 +6794,13 @@
         });
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
                     "s3", "s4");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10),
                     "s3", "s4", "s5");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_0),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10),
                     "s3", "s4", "s5", "s6");
             assertShortcutIds(
                     mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_P0),
@@ -6807,23 +6808,23 @@
             assertExpectException(
                     SecurityException.class, "unrelated profile", () -> {
                         mLauncherApps.getShortcuts(
-                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_11);
                     });
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_10),
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_1), HANDLE_USER_11),
                     "x4", "x5");
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_10)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_2), HANDLE_USER_11)
                     /* empty */);
             assertShortcutIds(
-                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_10)
+                    mLauncherApps.getShortcuts(buildPinnedQuery(CALLING_PACKAGE_3), HANDLE_USER_11)
                     /* empty */);
             assertExpectException(
                     SecurityException.class, "unrelated profile", () -> {
                         mLauncherApps.getShortcuts(
-                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0);
+                                buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_10);
                     });
             assertExpectException(
                     SecurityException.class, "unrelated profile", () -> {
@@ -6832,11 +6833,11 @@
                     });
         });
         // Check the user-IDs.
-        assertEquals(USER_0,
-                mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+        assertEquals(USER_10,
+                mService.getUserShortcutsLocked(USER_10).getPackageShortcuts(CALLING_PACKAGE_1)
                         .getOwnerUserId());
-        assertEquals(USER_0,
-                mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+        assertEquals(USER_10,
+                mService.getUserShortcutsLocked(USER_10).getPackageShortcuts(CALLING_PACKAGE_1)
                         .getPackageUserId());
         assertEquals(USER_P0,
                 mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
@@ -6845,27 +6846,27 @@
                 mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
                         .getPackageUserId());
 
-        assertEquals(USER_0,
-                mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+        assertEquals(USER_10,
+                mService.getUserShortcutsLocked(USER_10).getLauncherShortcuts(LAUNCHER_1, USER_10)
                         .getOwnerUserId());
-        assertEquals(USER_0,
-                mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+        assertEquals(USER_10,
+                mService.getUserShortcutsLocked(USER_10).getLauncherShortcuts(LAUNCHER_1, USER_10)
                         .getPackageUserId());
         assertEquals(USER_P0,
-                mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+                mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_10)
                         .getOwnerUserId());
-        assertEquals(USER_0,
-                mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+        assertEquals(USER_10,
+                mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_10)
                         .getPackageUserId());
     }
 
     public void OnApplicationActive_permission() {
         assertExpectException(SecurityException.class, "Missing permission", () ->
-                mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0));
+                mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10));
 
         // Has permission, now it should pass.
         mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
-        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0);
+        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10);
     }
 
     public void GetShareTargets_permission() {
@@ -6881,7 +6882,7 @@
         mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
         mManager.getShareTargets(filter);
 
-        runWithCaller(CHOOSER_ACTIVITY_PACKAGE, USER_0, () -> {
+        runWithCaller(CHOOSER_ACTIVITY_PACKAGE, USER_10, () -> {
             // Access is allowed when called from the configured system ChooserActivity
             mManager.getShareTargets(filter);
         });
@@ -6897,13 +6898,13 @@
     }
 
     public void isSharingShortcut_permission() throws IntentFilter.MalformedMimeTypeException {
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
 
         IntentFilter filter_any = new IntentFilter();
         filter_any.addDataType("*/*");
 
         assertExpectException(SecurityException.class, "Missing permission", () ->
-                mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+                mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                         filter_any));
 
         // Has permission, now it should pass.
@@ -6935,40 +6936,12 @@
 
         // Unlock user-0.
         mInjectedCurrentTimeMillis += 100;
-        mService.handleUnlockUser(USER_0);
-
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "ms1");
-            assertEmpty(mManager.getPinnedShortcuts());
-        });
-
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "ms1", "ms2");
-            assertEmpty(mManager.getPinnedShortcuts());
-        });
-
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
-            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
-                    mManager.getManifestShortcuts()))),
-                    "ms1", "ms2", "ms3", "ms4", "ms5");
-            assertEmpty(mManager.getPinnedShortcuts());
-        });
-
-        // Try on another user, with some packages uninstalled.
-        mRunningUsers.put(USER_10, true);
-
-        uninstallPackage(USER_10, CALLING_PACKAGE_1);
-        uninstallPackage(USER_10, CALLING_PACKAGE_3);
-
-        mInjectedCurrentTimeMillis += 100;
         mService.handleUnlockUser(USER_10);
 
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            assertEmpty(mManager.getManifestShortcuts());
+            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
+                    mManager.getManifestShortcuts()))),
+                    "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
@@ -6980,6 +6953,34 @@
         });
 
         runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
+            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
+                    mManager.getManifestShortcuts()))),
+                    "ms1", "ms2", "ms3", "ms4", "ms5");
+            assertEmpty(mManager.getPinnedShortcuts());
+        });
+
+        // Try on another user, with some packages uninstalled.
+        mRunningUsers.put(USER_11, true);
+
+        uninstallPackage(USER_11, CALLING_PACKAGE_1);
+        uninstallPackage(USER_11, CALLING_PACKAGE_3);
+
+        mInjectedCurrentTimeMillis += 100;
+        mService.handleUnlockUser(USER_11);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertEmpty(mManager.getManifestShortcuts());
+            assertEmpty(mManager.getPinnedShortcuts());
+        });
+
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
+            assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
+                    mManager.getManifestShortcuts()))),
+                    "ms1", "ms2");
+            assertEmpty(mManager.getPinnedShortcuts());
+        });
+
+        runWithCaller(CALLING_PACKAGE_3, USER_11, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
@@ -6999,23 +7000,23 @@
                 R.xml.shortcut_1);
 
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled( // FAIL
                     mManager.getManifestShortcuts()))),
                     "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
@@ -7031,23 +7032,23 @@
         updatePackageLastUpdateTime(CALLING_PACKAGE_3, 1);
 
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7055,12 +7056,12 @@
         });
 
         // Next, try removing all shortcuts, with some of them pinned.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms3"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("ms2"), HANDLE_USER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("ms1"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms3"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("ms2"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("ms1"), HANDLE_USER_10);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
@@ -7069,7 +7070,7 @@
                     "ms3");
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
@@ -7078,7 +7079,7 @@
                     "ms2");
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7106,16 +7107,16 @@
         updatePackageVersion(CALLING_PACKAGE_3, 1);
 
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertShortcutIds(assertAllImmutable(assertAllPinned(assertAllNotManifest(
                     assertAllDisabled(mManager.getPinnedShortcuts())))),
                     "ms3");
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7124,7 +7125,7 @@
                     "ms2");
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertShortcutIds(assertAllImmutable(assertAllPinned(assertAllNotManifest(
                     assertAllDisabled(mManager.getPinnedShortcuts())))),
@@ -7132,38 +7133,38 @@
         });
 
         // Make sure we don't have ShortcutPackage for packages that don't have shortcuts.
-        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_4, USER_0));
-        assertNull(mService.getPackageShortcutForTest(LAUNCHER_1, USER_0));
+        assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_4, USER_10));
+        assertNull(mService.getPackageShortcutForTest(LAUNCHER_1, USER_10));
     }
 
     public void ManifestShortcut_publishOnBroadcast() {
         // First, no packages are installed.
-        uninstallPackage(USER_0, CALLING_PACKAGE_1);
-        uninstallPackage(USER_0, CALLING_PACKAGE_2);
-        uninstallPackage(USER_0, CALLING_PACKAGE_3);
-        uninstallPackage(USER_0, CALLING_PACKAGE_4);
         uninstallPackage(USER_10, CALLING_PACKAGE_1);
         uninstallPackage(USER_10, CALLING_PACKAGE_2);
         uninstallPackage(USER_10, CALLING_PACKAGE_3);
         uninstallPackage(USER_10, CALLING_PACKAGE_4);
+        uninstallPackage(USER_11, CALLING_PACKAGE_1);
+        uninstallPackage(USER_11, CALLING_PACKAGE_2);
+        uninstallPackage(USER_11, CALLING_PACKAGE_3);
+        uninstallPackage(USER_11, CALLING_PACKAGE_4);
 
-        mService.handleUnlockUser(USER_0);
-
-        mRunningUsers.put(USER_10, true);
         mService.handleUnlockUser(USER_10);
 
+        mRunningUsers.put(USER_11, true);
+        mService.handleUnlockUser(USER_11);
+
         // Originally no manifest shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
@@ -7174,16 +7175,16 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
@@ -7195,16 +7196,16 @@
                 R.xml.shortcut_5_altalt);
         updatePackageVersion(CALLING_PACKAGE_2, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
@@ -7221,8 +7222,8 @@
         dumpsysOnLogcat("Before pinning");
 
         // Also pin some.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("ms2", "ms3"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("ms2", "ms3"), HANDLE_USER_10);
         });
 
         dumpsysOnLogcat("After pinning");
@@ -7232,18 +7233,18 @@
                 R.xml.shortcut_2);
         updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
 
         dumpsysOnLogcat("After updating package 2");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
             assertEmpty(mManager.getPinnedShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
@@ -7267,10 +7268,10 @@
         });
 
         // Make sure the launcher see the correct disabled reason.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertWith(getShortcutAsLauncher(USER_0))
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            assertWith(getShortcutAsLauncher(USER_10))
                     .forShortcutWithId("ms3", si -> {
-                        assertEquals("string-com.android.test.2-user:0-res:"
+                        assertEquals("string-com.android.test.2-user:10-res:"
                                         + R.string.shortcut_disabled_message3 + "/en",
                                 si.getDisabledMessage());
                     });
@@ -7278,18 +7279,18 @@
 
 
         // Package 2 on user 10 has no shortcuts yet.
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
         });
         // Send add broadcast, but the user is not running, so should be ignored.
-        mService.handleStopUser(USER_10);
-        mRunningUsers.put(USER_10, false);
-        mUnlockedUsers.put(USER_10, false);
+        mService.handleStopUser(USER_11);
+        mRunningUsers.put(USER_11, false);
+        mUnlockedUsers.put(USER_11, false);
 
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_11));
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             // Don't use the mManager APIs to get shortcuts, because they'll trigger the package
             // update check.
             // So look the internal data directly using getCallerShortcuts().
@@ -7297,10 +7298,10 @@
         });
 
         // Try again, but the user is locked, so still ignored.
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_11));
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             // Don't use the mManager APIs to get shortcuts, because they'll trigger the package
             // update check.
             // So look the internal data directly using getCallerShortcuts().
@@ -7308,13 +7309,13 @@
         });
 
         // Unlock the user, now it should work.
-        mUnlockedUsers.put(USER_10, true);
+        mUnlockedUsers.put(USER_11, true);
 
         // Send PACKAGE_ADD broadcast to have Package 2 on user-10 publish manifest shortcuts.
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
@@ -7326,7 +7327,7 @@
         });
 
         // But it shouldn't affect user-0.
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2");
@@ -7353,9 +7354,9 @@
 
         updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5",
@@ -7381,10 +7382,10 @@
                 R.xml.shortcut_0);
         updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
 
         // No manifest shortcuts, and pinned ones are disabled.
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertShortcutIds(assertAllImmutable(assertAllPinned(assertAllDisabled(
                     mManager.getPinnedShortcuts()))),
@@ -7394,15 +7395,15 @@
 
     public void ManifestShortcuts_missingMandatoryFields() {
         // Start with no apps installed.
-        uninstallPackage(USER_0, CALLING_PACKAGE_1);
-        uninstallPackage(USER_0, CALLING_PACKAGE_2);
-        uninstallPackage(USER_0, CALLING_PACKAGE_3);
-        uninstallPackage(USER_0, CALLING_PACKAGE_4);
+        uninstallPackage(USER_10, CALLING_PACKAGE_1);
+        uninstallPackage(USER_10, CALLING_PACKAGE_2);
+        uninstallPackage(USER_10, CALLING_PACKAGE_3);
+        uninstallPackage(USER_10, CALLING_PACKAGE_4);
 
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Make sure no manifest shortcuts.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
         });
 
@@ -7412,10 +7413,10 @@
                 R.xml.shortcut_error_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .areAllManifest()
                     .areAllImmutable()
@@ -7429,10 +7430,10 @@
                 R.xml.shortcut_error_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .areAllManifest()
                     .areAllImmutable()
@@ -7446,10 +7447,10 @@
                 R.xml.shortcut_error_3);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .areAllManifest()
                     .areAllImmutable()
@@ -7467,9 +7468,9 @@
                 R.xml.shortcut_error_4);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // Make sure invalid ones are not published.
             // Note that at this point disabled ones don't show up because they weren't pinned.
             assertWith(getCallerShortcuts())
@@ -7525,9 +7526,9 @@
                 R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // Make sure 5 manifest shortcuts are published.
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
@@ -7538,13 +7539,13 @@
                     .areAllEnabled();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    list("ms3", "ms4", "ms5"), HANDLE_USER_0);
+                    list("ms3", "ms4", "ms5"), HANDLE_USER_10);
         });
 
         // Make sure they're pinned.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
                     .selectByIds("ms1", "ms2")
@@ -7563,10 +7564,10 @@
                 R.xml.shortcut_error_4);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Make sure 3, 4 and 5 still exist but disabled.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
                     .areAllNotDynamic()
@@ -7604,7 +7605,7 @@
     }
 
     public void ManifestShortcuts_checkAllFields() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Package 1 updated, which has one valid manifest shortcut and one invalid.
         addManifestShortcutResource(
@@ -7612,10 +7613,10 @@
                 R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "ms3", "ms4", "ms5")
                     .areAllManifest()
@@ -7709,7 +7710,7 @@
     }
 
     public void ManifestShortcuts_localeChange() throws InterruptedException {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Package 1 updated, which has one valid manifest shortcut and one invalid.
         addManifestShortcutResource(
@@ -7717,9 +7718,9 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.setDynamicShortcuts(list(makeShortcutWithTitle("s1", "title")));
 
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
@@ -7730,11 +7731,11 @@
             ShortcutInfo si = getCallerShortcut("ms1");
 
             assertEquals("ms1", si.getId());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_title1 + "/en",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_title1 + "/en",
                     si.getTitle());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_text1 + "/en",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_text1 + "/en",
                     si.getText());
-            assertEquals("string-com.android.test.1-user:0-res:"
+            assertEquals("string-com.android.test.1-user:10-res:"
                             + R.string.shortcut_disabled_message1 + "/en",
                     si.getDisabledMessage());
             assertEquals(START_TIME, si.getLastChangedTimestamp());
@@ -7743,11 +7744,11 @@
             si = getCallerShortcut("ms2");
 
             assertEquals("ms2", si.getId());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_title2 + "/en",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_title2 + "/en",
                     si.getTitle());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_text2 + "/en",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_text2 + "/en",
                     si.getText());
-            assertEquals("string-com.android.test.1-user:0-res:"
+            assertEquals("string-com.android.test.1-user:10-res:"
                             + R.string.shortcut_disabled_message2 + "/en",
                     si.getDisabledMessage());
             assertEquals(START_TIME, si.getLastChangedTimestamp());
@@ -7767,23 +7768,23 @@
         // Change the locale and send the broadcast, make sure the launcher gets a callback too.
         mInjectedLocale = Locale.JAPANESE;
 
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
 
         assertForLauncherCallback(mLauncherApps, () -> {
             mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
-        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+        }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_10)
                 .haveIds("ms1", "ms2", "s1");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // check first shortcut.
             ShortcutInfo si = getCallerShortcut("ms1");
 
             assertEquals("ms1", si.getId());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_title1 + "/ja",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_title1 + "/ja",
                     si.getTitle());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_text1 + "/ja",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_text1 + "/ja",
                     si.getText());
-            assertEquals("string-com.android.test.1-user:0-res:"
+            assertEquals("string-com.android.test.1-user:10-res:"
                             + R.string.shortcut_disabled_message1 + "/ja",
                     si.getDisabledMessage());
             assertEquals(START_TIME + 1, si.getLastChangedTimestamp());
@@ -7792,11 +7793,11 @@
             si = getCallerShortcut("ms2");
 
             assertEquals("ms2", si.getId());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_title2 + "/ja",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_title2 + "/ja",
                     si.getTitle());
-            assertEquals("string-com.android.test.1-user:0-res:" + R.string.shortcut_text2 + "/ja",
+            assertEquals("string-com.android.test.1-user:10-res:" + R.string.shortcut_text2 + "/ja",
                     si.getText());
-            assertEquals("string-com.android.test.1-user:0-res:"
+            assertEquals("string-com.android.test.1-user:10-res:"
                             + R.string.shortcut_disabled_message2 + "/ja",
                     si.getDisabledMessage());
             assertEquals(START_TIME + 1, si.getLastChangedTimestamp());
@@ -7813,7 +7814,7 @@
     }
 
     public void ManifestShortcuts_updateAndDisabled_notPinned() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // First, just publish a manifest shortcut.
         addManifestShortcutResource(
@@ -7821,10 +7822,10 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7840,10 +7841,10 @@
                 R.xml.shortcut_1_disable);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Because shortcut 1 wasn't pinned, it'll just go away.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertEmpty(mManager.getPinnedShortcuts());
 
@@ -7853,7 +7854,7 @@
     }
 
     public void ManifestShortcuts_updateAndDisabled_pinned() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // First, just publish a manifest shortcut.
         addManifestShortcutResource(
@@ -7861,10 +7862,10 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Only the valid one is published.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7874,8 +7875,8 @@
             assertShortcutIds(getCallerShortcuts(), "ms1");
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_10);
         });
 
         // Now upgrade, the manifest shortcut is disabled now.
@@ -7884,10 +7885,10 @@
                 R.xml.shortcut_1_disable);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // Because shortcut 1 was pinned, it'll still exist as pinned, but disabled.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEmpty(mManager.getManifestShortcuts());
             assertShortcutIds(assertAllNotManifest(assertAllImmutable(assertAllDisabled(
                     mManager.getPinnedShortcuts()))),
@@ -7909,7 +7910,7 @@
     }
 
     public void ManifestShortcuts_duplicateInSingleActivity() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // The XML has two shortcuts with the same ID.
         addManifestShortcutResource(
@@ -7917,9 +7918,9 @@
                 R.xml.shortcut_2_duplicate);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1");
@@ -7934,7 +7935,7 @@
     }
 
     public void ManifestShortcuts_duplicateInTwoActivities() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // ShortcutActivity has shortcut ms1
         addManifestShortcutResource(
@@ -7947,9 +7948,9 @@
                 R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllManifest(assertAllImmutable(assertAllEnabled(
                     mManager.getManifestShortcuts()))),
                     "ms1", "ms2", "ms3", "ms4", "ms5");
@@ -7986,11 +7987,11 @@
      * Manifest shortcuts cannot override shortcuts that were published via the APIs.
      */
     public void ManifestShortcuts_cannotOverrideNonManifest() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Create a non-pinned dynamic shortcut and a non-dynamic pinned shortcut.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.setDynamicShortcuts(list(
                     makeShortcut("ms1", "title1",
                             new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
@@ -8000,11 +8001,11 @@
                     /* icon */ null, new Intent("action1"), /* rank */ 0)));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2"), HANDLE_USER_10);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("ms2"));
 
             assertShortcutIds(mManager.getDynamicShortcuts(), "ms1");
@@ -8019,9 +8020,9 @@
                 R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllNotManifest(mManager.getDynamicShortcuts()), "ms1");
             assertShortcutIds(assertAllNotManifest(mManager.getPinnedShortcuts()), "ms2");
             assertShortcutIds(assertAllManifest(mManager.getManifestShortcuts()),
@@ -8037,7 +8038,7 @@
     }
 
     protected void checkManifestShortcuts_immutable_verify() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertShortcutIds(assertAllNotManifest(assertAllEnabled(
                     mManager.getDynamicShortcuts())),
                     "s1");
@@ -8059,7 +8060,7 @@
      * Make sure the APIs won't work on manifest shortcuts.
      */
     public void ManifestShortcuts_immutable() {
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         // Create a non-pinned manifest shortcut, a pinned shortcut that was originally
         // a manifest shortcut, as well as a dynamic shortcut.
@@ -8069,10 +8070,10 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2"), HANDLE_USER_10);
         });
 
         addManifestShortcutResource(
@@ -8080,9 +8081,9 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.addDynamicShortcuts(list(makeShortcutWithTitle("s1", "t1")));
         });
 
@@ -8091,7 +8092,7 @@
         // Note that even though the first argument is not immutable and only the second one
         // is immutable, the first argument should not be executed either.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.setDynamicShortcuts(list(makeShortcut("xx"), makeShortcut("ms1")));
             });
@@ -8101,7 +8102,7 @@
         });
         checkManifestShortcuts_immutable_verify();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.addDynamicShortcuts(list(makeShortcut("xx"), makeShortcut("ms1")));
             });
@@ -8112,7 +8113,7 @@
         checkManifestShortcuts_immutable_verify();
 
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.updateShortcuts(list(makeShortcut("s1"), makeShortcut("ms1")));
             });
@@ -8122,7 +8123,7 @@
         });
         checkManifestShortcuts_immutable_verify();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.removeDynamicShortcuts(list("s1", "ms1"));
             });
@@ -8132,14 +8133,14 @@
         });
         checkManifestShortcuts_immutable_verify();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.disableShortcuts(list("s1", "ms1"));
             });
         });
         checkManifestShortcuts_immutable_verify();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertCannotUpdateImmutable(() -> {
                 mManager.enableShortcuts(list("s1", "ms2"));
             });
@@ -8155,16 +8156,16 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         addManifestShortcutResource(
                 new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
                 R.xml.shortcut_5);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
                 mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // Only the first 3 should be published.
             assertShortcutIds(mManager.getManifestShortcuts(), "ms1", "ms2", "ms3");
         });
@@ -8174,7 +8175,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ComponentName a1 = new ComponentName(mClientContext, ShortcutActivity.class);
             final ComponentName a2 = new ComponentName(mClientContext, ShortcutActivity2.class);
             final ShortcutInfo s1_1 = makeShortcutWithActivity("s11", a1);
@@ -8232,7 +8233,7 @@
                     R.xml.shortcut_2);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
             assertEquals(2, mManager.getManifestShortcuts().size());
 
             // Setting 1 to activity 1 will work.
@@ -8255,7 +8256,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ComponentName a1 = new ComponentName(mClientContext, ShortcutActivity.class);
             final ComponentName a2 = new ComponentName(mClientContext, ShortcutActivity2.class);
             final ShortcutInfo s1_1 = makeShortcutWithActivity("s11", a1);
@@ -8305,9 +8306,9 @@
 
             // Make sure pinned shortcuts won't affect.
             // - Pin s11 - s13, and remove all dynamic.
-            runWithCaller(LAUNCHER_1, USER_0, () -> {
+            runWithCaller(LAUNCHER_1, USER_10, () -> {
                 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s11", "s12", "s13"),
-                        HANDLE_USER_0);
+                        HANDLE_USER_10);
             });
             mManager.removeAllDynamicShortcuts();
 
@@ -8358,7 +8359,7 @@
                     R.xml.shortcut_2);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
             assertEquals(2, mManager.getManifestShortcuts().size());
 
@@ -8382,7 +8383,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ComponentName a1 = new ComponentName(mClientContext, ShortcutActivity.class);
             final ComponentName a2 = new ComponentName(mClientContext, ShortcutActivity2.class);
             final ShortcutInfo s1_1 = makeShortcutWithActivity("s11", a1);
@@ -8431,9 +8432,9 @@
                     "s11", "s12", "s13", "s21", "s22", "s23");
 
             // Pin some to have more shortcuts for a1.
-            runWithCaller(LAUNCHER_1, USER_0, () -> {
+            runWithCaller(LAUNCHER_1, USER_10, () -> {
                 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s11", "s12", "s13"),
-                        HANDLE_USER_0);
+                        HANDLE_USER_10);
             });
             mManager.setDynamicShortcuts(list(s1_4, s1_5, s2_1, s2_2, s2_3));
             assertShortcutIds(mManager.getDynamicShortcuts(),
@@ -8473,7 +8474,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             final ComponentName a1 = new ComponentName(mClientContext, ShortcutActivity.class);
             final ComponentName a2 = new ComponentName(mClientContext, ShortcutActivity2.class);
             final ShortcutInfo s1_1 = makeShortcutWithActivityAndRank("s11", a1, 4);
@@ -8489,9 +8490,9 @@
 
             // Initial state.
             mManager.setDynamicShortcuts(list(s1_1, s1_2, s1_3, s2_1, s2_2, s2_3));
-            runWithCaller(LAUNCHER_1, USER_0, () -> {
+            runWithCaller(LAUNCHER_1, USER_10, () -> {
                 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s11", "s12", "s21", "s22"),
-                        HANDLE_USER_0);
+                        HANDLE_USER_10);
             });
             mManager.setDynamicShortcuts(list(s1_2, s1_3, s1_4, s2_2, s2_3, s2_4));
             assertShortcutIds(assertAllEnabled(mManager.getDynamicShortcuts()),
@@ -8507,7 +8508,7 @@
                     R.xml.shortcut_1);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
             assertEquals(1, mManager.getManifestShortcuts().size());
 
             // s12 removed.
@@ -8527,7 +8528,7 @@
                     R.xml.shortcut_1_alt);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
             assertEquals(3, mManager.getManifestShortcuts().size());
 
             // Note the ones with the highest rank values (== least important) will be removed.
@@ -8547,7 +8548,7 @@
                     R.xml.shortcut_5_alt); // manifest has 5, but max is 3, so a2 will have 3.
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
             assertEquals(5, mManager.getManifestShortcuts().size());
 
             assertShortcutIds(assertAllEnabled(mManager.getDynamicShortcuts()),
@@ -8566,7 +8567,7 @@
                     R.xml.shortcut_0);
             updatePackageVersion(CALLING_PACKAGE_1, 1);
                     mService.mPackageMonitor.onReceive(getTestContext(),
-                    genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                    genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
             assertEquals(0, mManager.getManifestShortcuts().size());
 
             assertShortcutIds(assertAllEnabled(mManager.getDynamicShortcuts()),
@@ -8584,9 +8585,9 @@
                 R.xml.shortcut_1);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(mManager.getManifestShortcuts())
                     .haveIds("ms1")
                     .forAllShortcuts(si -> assertTrue(si.isReturnedByServer()));
@@ -8599,21 +8600,21 @@
         });
 
         // Pin them.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
                     list("ms1", "s1"), getCallingUser());
-            assertWith(getShortcutAsLauncher(USER_0))
+            assertWith(getShortcutAsLauncher(USER_10))
                     .haveIds("ms1", "s1")
                     .forAllShortcuts(si -> assertTrue(si.isReturnedByServer()));
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(mManager.getPinnedShortcuts())
                     .haveIds("ms1", "s1")
                     .forAllShortcuts(si -> assertTrue(si.isReturnedByServer()));
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // This shows a warning log, but should still work.
             assertTrue(mManager.setDynamicShortcuts(mManager.getDynamicShortcuts()));
 
@@ -8624,9 +8625,10 @@
     }
 
     public void IsForegroundDefaultLauncher_true() {
-        final int uid = 1024;
+        // random uid in the USER_10 range.
+        final int uid = 1000024;
 
-        setDefaultLauncher(UserHandle.USER_SYSTEM, "default");
+        setDefaultLauncher(USER_10, "default");
         makeUidForeground(uid);
 
         assertTrue(mInternal.isForegroundDefaultLauncher("default", uid));
@@ -8634,18 +8636,20 @@
 
 
     public void IsForegroundDefaultLauncher_defaultButNotForeground() {
-        final int uid = 1024;
+        // random uid in the USER_10 range.
+        final int uid = 1000024;
 
-        setDefaultLauncher(UserHandle.USER_SYSTEM, "default");
+        setDefaultLauncher(USER_10, "default");
         makeUidBackground(uid);
 
         assertFalse(mInternal.isForegroundDefaultLauncher("default", uid));
     }
 
     public void IsForegroundDefaultLauncher_foregroundButNotDefault() {
-        final int uid = 1024;
+        // random uid in the USER_10 range.
+        final int uid = 1000024;
 
-        setDefaultLauncher(UserHandle.USER_SYSTEM, "default");
+        setDefaultLauncher(USER_10, "default");
         makeUidForeground(uid);
 
         assertFalse(mInternal.isForegroundDefaultLauncher("another", uid));
@@ -8670,7 +8674,7 @@
                 R.xml.shortcut_share_targets);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         List<ShareTargetInfo> shareTargets = getCallerShareTargets();
 
@@ -8775,9 +8779,9 @@
                 R.xml.shortcut_share_targets);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final ShortcutInfo s1 = makeShortcutWithCategory("s1",
                 set("com.test.category.CATEGORY1", "com.test.category.CATEGORY2"));
@@ -8796,26 +8800,26 @@
         IntentFilter filter_any = new IntentFilter();
         filter_any.addDataType("*/*");
 
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
         mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
 
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                 filter_cat1));
-        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+        assertFalse(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                 filter_cat5));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                 filter_any));
 
-        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+        assertFalse(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_10,
                 filter_cat1));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_10,
                 filter_cat5));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_10,
                 filter_any));
 
-        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_0,
+        assertFalse(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_10,
                 filter_any));
-        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s4", USER_0,
+        assertFalse(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s4", USER_10,
                 filter_any));
     }
 
@@ -8826,7 +8830,7 @@
                 R.xml.shortcut_share_targets);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         final ShortcutInfo s1 = makeShortcutWithCategory("s1",
                 set("com.test.category.CATEGORY1", "com.test.category.CATEGORY2"));
@@ -8837,7 +8841,7 @@
         s1.setLongLived();
         s2.setLongLived();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(s1, s2, s3)));
             assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
                     "s1", "s2", "s3");
@@ -8846,33 +8850,33 @@
         IntentFilter filter_any = new IntentFilter();
         filter_any.addDataType("*/*");
 
-        setCaller(LAUNCHER_1, USER_0);
+        setCaller(LAUNCHER_1, USER_10);
         mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
 
         // Assert all are sharing shortcuts
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                 filter_any));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_10,
                 filter_any));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_10,
                 filter_any));
 
         mInjectCheckAccessShortcutsPermission = true;
-        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0,
+        mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_10,
                 CACHE_OWNER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             // Remove one cached shortcut, and leave one cached-only and pinned-only shortcuts.
             mManager.removeLongLivedShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s2, s3"));
         });
 
-        assertFalse(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_0,
+        assertFalse(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s1", USER_10,
                 filter_any));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s2", USER_10,
                 filter_any));
-        assertTrue(mInternal.isSharingShortcut(USER_0, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_0,
+        assertTrue(mInternal.isSharingShortcut(USER_10, LAUNCHER_1, CALLING_PACKAGE_1, "s3", USER_10,
                 filter_any));
     }
 
@@ -8881,17 +8885,17 @@
         final ShortcutInfo s2 = makeShortcutExcludedFromLauncher("s2");
         final ShortcutInfo s3 = makeShortcutExcludedFromLauncher("s3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(s1, s2, s3)));
             assertEmpty(mManager.getDynamicShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(s1, s2, s3)));
             assertEmpty(mManager.getDynamicShortcuts());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.pushDynamicShortcut(s1);
             assertEmpty(mManager.getDynamicShortcuts());
         });
@@ -8902,7 +8906,7 @@
         final ShortcutInfo s2 = makeShortcut("s2");
         final ShortcutInfo s3 = makeShortcut("s3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(s1, s2, s3)));
             assertThrown(IllegalArgumentException.class, () -> {
                 mManager.updateShortcuts(list(makeShortcutExcludedFromLauncher("s1")));
@@ -8911,7 +8915,7 @@
     }
 
     public void PinHiddenShortcuts_ThrowsException() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertThrown(IllegalArgumentException.class, () -> {
                 mManager.requestPinShortcut(makeShortcutExcludedFromLauncher("s1"), null);
             });
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
index 57ada9b..748f0a5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
@@ -28,7 +28,6 @@
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
-import android.os.Process;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
@@ -56,7 +55,7 @@
     }
 
     public void testCreateShortcutResult_validResult() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
@@ -64,20 +63,20 @@
             mRequest = verifyAndGetCreateShortcutResult(intent);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertTrue(mRequest.isValid());
             assertTrue(mRequest.accept());
         });
     }
 
     public void testCreateShortcutResult_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
@@ -87,7 +86,7 @@
             mRequest = verifyAndGetCreateShortcutResult(intent);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertTrue(mRequest.isValid());
             assertTrue(mRequest.getShortcutInfo().isPinned());
             assertTrue(mRequest.accept());
@@ -100,18 +99,18 @@
         });
 
         // Initially all launchers have the shortcut permission, until we call setDefaultLauncher().
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
             Intent intent = mManager.createShortcutResultIntent(s1);
             mRequest = verifyAndGetCreateShortcutResult(intent);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertTrue(mRequest.isValid());
             assertFalse(mRequest.getShortcutInfo().isPinned());
             assertTrue(mRequest.accept());
@@ -119,7 +118,7 @@
     }
 
     public void testCreateShortcutResult_defaultLauncherChanges() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
@@ -127,15 +126,15 @@
             mRequest = verifyAndGetCreateShortcutResult(intent);
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_2);
         // Verify that other launcher can't use this request
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             assertFalse(mRequest.isValid());
             assertExpectException(SecurityException.class, "Calling uid mismatch",
                     mRequest::accept);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Set some random caller UID.
             mInjectedCallingUid = 12345;
 
@@ -144,7 +143,7 @@
                     mRequest::accept);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertTrue(mRequest.isValid());
             assertTrue(mRequest.accept());
         });
@@ -157,23 +156,23 @@
         LauncherActivityInfo info = mock(LauncherActivityInfo.class);
         when(info.getComponentName()).thenReturn(
                 new ComponentName(getTestContext(), "a.ShortcutConfigActivity"));
-        when(info.getUser()).thenReturn(Process.myUserHandle());
+        when(info.getUser()).thenReturn(HANDLE_USER_10);
         return info;
     }
 
     public void testStartConfigActivity_defaultLauncher() {
         LauncherActivityInfo info = setupMockActivityInfo();
         prepareIntentActivities(info.getComponentName());
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () ->
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () ->
             assertNotNull(mLauncherApps.getShortcutConfigActivityIntent(info))
         );
     }
 
     public void testStartConfigActivity_nonDefaultLauncher() {
         LauncherActivityInfo info = setupMockActivityInfo();
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_2, USER_0, () ->
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_2, USER_10, () ->
             assertExpectException(SecurityException.class, null, () ->
                     mLauncherApps.getShortcutConfigActivityIntent(info))
         );
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
index 98fa2d6..676558d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
@@ -56,12 +56,12 @@
 
     public void testShortcutChangeCallback_setDynamicShortcuts() {
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
@@ -69,7 +69,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -78,17 +78,17 @@
     }
 
     public void testShortcutChangeCallback_setDynamicShortcuts_replaceSameId() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s2", "s3")));
         });
 
@@ -96,11 +96,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -112,25 +112,25 @@
     }
 
     public void testShortcutChangeCallback_setDynamicShortcuts_pinnedAndCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(
                     list(makeShortcut("s1"), makeLongLivedShortcut("s2"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10);
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s3", "s4")));
         });
 
@@ -138,7 +138,7 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(changedShortcuts.getValue())
@@ -147,22 +147,22 @@
     }
 
     public void testShortcutChangeCallback_pinShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10);
         });
 
         mTestLooper.dispatchAll();
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -171,34 +171,34 @@
     }
 
     public void testShortcutChangeCallback_pinShortcuts_unpinOthers() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2", "s3")));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_10);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s1", "s2"));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"), HANDLE_USER_10);
         });
 
         mTestLooper.dispatchAll();
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -210,19 +210,19 @@
     }
 
     public void testShortcutChangeCallback_cacheShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_1);
         });
 
@@ -230,7 +230,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(2)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -239,23 +239,23 @@
     }
 
     public void testShortcutChangeCallback_cacheShortcuts_alreadyCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
             // Should not cause any callback events
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_0);
             // Should cause a change event
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_1);
         });
 
@@ -263,7 +263,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -272,19 +272,19 @@
     }
 
     public void testShortcutChangeCallback_uncacheShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
         });
 
@@ -292,7 +292,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -301,41 +301,41 @@
     }
 
     public void testShortcutChangeCallback_uncacheShortcuts_causeDeletion() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeLongLivedShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeLongLivedShortcut("s3"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0,
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10);
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10,
                     CACHE_OWNER_1);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s2", "s3"));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
-            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"), HANDLE_USER_0,
-                    CACHE_OWNER_0);
+            mLauncherApps.uncacheShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3"),
+                    HANDLE_USER_10, CACHE_OWNER_0);
         });
 
         mTestLooper.dispatchAll();
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         // s1 is still cached for owner1, s2 is pinned.
         assertWith(changedShortcuts.getValue())
@@ -348,19 +348,19 @@
     }
 
     public void testShortcutChangeCallback_updateShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeShortcutWithActivity("s2", new ComponentName(CALLING_PACKAGE_1, "test")))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
         final ComponentName updatedCn = new ComponentName(CALLING_PACKAGE_1, "updated activity");
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.updateShortcuts(list(makeShortcutWithActivity("s2", updatedCn))));
         });
 
@@ -368,7 +368,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -378,17 +378,17 @@
     }
 
     public void testShortcutChangeCallback_addDynamicShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.addDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
@@ -396,7 +396,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -406,12 +406,12 @@
 
     public void testShortcutChangeCallback_pushDynamicShortcut() {
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.pushDynamicShortcut(makeShortcut("s1"));
         });
 
@@ -419,7 +419,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -431,17 +431,17 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.pushDynamicShortcut(makeShortcut("s2"));
         });
 
@@ -449,7 +449,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -461,17 +461,17 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2", "s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.pushDynamicShortcut(makeShortcut("s4"));
         });
 
@@ -479,11 +479,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -498,7 +498,7 @@
         // Change the max number of shortcuts.
         mService.updateConfigurationLocked(ConfigConstants.KEY_MAX_SHORTCUTS + "=3");
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts((makeShortcuts("s1", "s2"))));
             ShortcutInfo s3 = makeLongLivedShortcut("s3");
             s3.setRank(3);
@@ -506,15 +506,15 @@
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10,
                     CACHE_OWNER_0);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.pushDynamicShortcut(makeShortcut("s4"));
         });
 
@@ -522,7 +522,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -532,17 +532,17 @@
 
     public void testShortcutChangeCallback_disableShortcuts() {
         updatePackageVersion(CALLING_PACKAGE_1, 1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.disableShortcuts(list("s2"));
         });
 
@@ -552,7 +552,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -560,22 +560,22 @@
     }
 
     public void testShortcutChangeCallback_disableShortcuts_pinnedAndCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(
                     list(makeShortcut("s1"), makeLongLivedShortcut("s2"), makeShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.disableShortcuts(list("s1", "s2", "s3"));
         });
 
@@ -583,11 +583,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -599,29 +599,29 @@
     }
 
     public void testShortcutChangeCallback_enableShortcuts() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(
                     list(makeShortcut("s1"), makeLongLivedShortcut("s2"), makeShortcut("s3"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.disableShortcuts(list("s1", "s2", "s3"));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.enableShortcuts(list("s1", "s2", "s3"));
         });
 
@@ -629,7 +629,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
         verify(callback, times(0)).onShortcutsRemoved(any(), any(), any());
 
         assertWith(shortcuts.getValue())
@@ -639,17 +639,17 @@
 
     public void testShortcutChangeCallback_removeDynamicShortcuts() {
         updatePackageVersion(CALLING_PACKAGE_1, 1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s2"));
         });
 
@@ -659,7 +659,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -667,22 +667,22 @@
     }
 
     public void testShortcutChangeCallback_removeDynamicShortcuts_pinnedAndCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeShortcut("s3"), makeShortcut("s4"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeDynamicShortcuts(list("s1", "s2", "s3"));
         });
 
@@ -690,11 +690,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -707,17 +707,17 @@
 
     public void testShortcutChangeCallback_removeAllDynamicShortcuts() {
         updatePackageVersion(CALLING_PACKAGE_1, 1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(makeShortcuts("s1", "s2")));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
         });
 
@@ -727,7 +727,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -735,22 +735,22 @@
     }
 
     public void testShortcutChangeCallback_removeAllDynamicShortcuts_pinnedAndCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(
                     list(makeShortcut("s1"), makeLongLivedShortcut("s2"), makeShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeAllDynamicShortcuts();
         });
 
@@ -758,11 +758,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -775,18 +775,18 @@
 
     public void testShortcutChangeCallback_removeLongLivedShortcuts_notCached() {
         updatePackageVersion(CALLING_PACKAGE_1, 1);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeShortcut("s3"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeLongLivedShortcuts(list("s1", "s2"));
         });
 
@@ -796,7 +796,7 @@
 
         ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), shortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(shortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
@@ -804,22 +804,22 @@
     }
 
     public void testShortcutChangeCallback_removeLongLivedShortcuts_pinnedAndCached() {
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"),
                     makeLongLivedShortcut("s2"), makeShortcut("s3"), makeShortcut("s4"))));
         });
 
         ShortcutChangeCallback callback = mock(ShortcutChangeCallback.class);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_10,
                     CACHE_OWNER_0);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_10);
             mLauncherApps.registerShortcutChangeCallback(callback, QUERY_MATCH_ALL,
                     mTestLooper.getNewExecutor());
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.removeLongLivedShortcuts(list("s1", "s2", "s3"));
         });
 
@@ -827,11 +827,11 @@
 
         ArgumentCaptor<List> changedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsAddedOrUpdated(
-                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), changedShortcuts.capture(), eq(HANDLE_USER_10));
 
         ArgumentCaptor<List> removedShortcuts = ArgumentCaptor.forClass(List.class);
         verify(callback, times(1)).onShortcutsRemoved(
-                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_0));
+                eq(CALLING_PACKAGE_1), removedShortcuts.capture(), eq(HANDLE_USER_10));
 
         assertWith(changedShortcuts.getValue())
                 .areAllWithKeyFieldsOnly()
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
index 78bcf0c..10e8bf0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
@@ -50,21 +50,21 @@
     @Override
     protected void tearDown() throws Exception {
         if (mService.isAppSearchEnabled()) {
-            setCaller(CALLING_PACKAGE_1, USER_0);
-            mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+            setCaller(CALLING_PACKAGE_1, USER_10);
+            mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_10)
                     .removeAllShortcutsAsync();
         }
         super.tearDown();
     }
 
     public void testGetShortcutIntents_ReturnsMutablePendingIntents() throws RemoteException {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () ->
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () ->
                 assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))))
         );
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             final PendingIntent intent = mLauncherApps.getShortcutIntent(
                     CALLING_PACKAGE_1, "s1", null, UserHandle.SYSTEM);
             assertNotNull(intent);
@@ -75,7 +75,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         // Verifies setDynamicShortcuts persists shortcuts into AppSearch
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
@@ -102,7 +102,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -126,7 +126,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -168,7 +168,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -194,7 +194,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -218,7 +218,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -243,7 +243,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcut("s1"),
                 makeShortcut("s2"),
@@ -266,7 +266,7 @@
         if (!mService.isAppSearchEnabled()) {
             return;
         }
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
         mManager.setDynamicShortcuts(list(
                 makeShortcutExcludedFromLauncher("s1"),
                 makeShortcutExcludedFromLauncher("s2"),
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 1cfaf7c..9528467 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -238,15 +238,15 @@
     }
 
     public void testShortcutInfoParcel() {
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
         ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setTitle("title")
                 .setIntent(makeIntent("action", ShortcutActivity.class))
                 .build());
         assertEquals(mClientContext.getPackageName(), si.getPackage());
-        assertEquals(USER_10, si.getUserId());
-        assertEquals(HANDLE_USER_10, si.getUserHandle());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
         assertEquals("id", si.getId());
         assertEquals("title", si.getTitle());
         assertEquals("action", si.getIntent().getAction());
@@ -325,7 +325,7 @@
     }
 
     public void testShortcutInfoParcel_resId() {
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
         ShortcutInfo si;
 
         PersistableBundle pb = new PersistableBundle();
@@ -379,7 +379,7 @@
     }
 
     public void testShortcutInfoClone() {
-        setCaller(CALLING_PACKAGE_1, USER_11);
+        setCaller(CALLING_PACKAGE_1, USER_12);
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
@@ -406,8 +406,8 @@
 
         ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
 
-        assertEquals(USER_11, si.getUserId());
-        assertEquals(HANDLE_USER_11, si.getUserHandle());
+        assertEquals(USER_12, si.getUserId());
+        assertEquals(HANDLE_USER_12, si.getUserHandle());
         assertEquals(mClientContext.getPackageName(), si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(new ComponentName("a", "b"), si.getActivity());
@@ -527,7 +527,7 @@
     }
 
     public void testShortcutInfoClone_resId() {
-        setCaller(CALLING_PACKAGE_1, USER_11);
+        setCaller(CALLING_PACKAGE_1, USER_12);
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
@@ -552,8 +552,8 @@
 
         ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
 
-        assertEquals(USER_11, si.getUserId());
-        assertEquals(HANDLE_USER_11, si.getUserHandle());
+        assertEquals(USER_12, si.getUserId());
+        assertEquals(HANDLE_USER_12, si.getUserHandle());
         assertEquals(mClientContext.getPackageName(), si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(new ComponentName("a", "b"), si.getActivity());
@@ -953,9 +953,9 @@
     }
 
     public void testShortcutInfoSaveAndLoad() throws InterruptedException {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
 
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
@@ -1010,16 +1010,16 @@
         // Save and load.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
-        dumpUserFile(USER_10);
+        dumpUserFile(USER_11);
         dumpsysOnLogcat("after load");
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_11);
 
-        assertEquals(USER_10, si.getUserId());
-        assertEquals(HANDLE_USER_10, si.getUserHandle());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
@@ -1056,19 +1056,19 @@
 
         // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
         // to test it.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_11);
         assertEquals(1, si.getRank());
         assertEquals(2, si.getPersons().length);
         assertEquals("personUri2", si.getPersons()[1].getUri());
         assertEquals("6.7.8.9", si.getLocusId().getId());
 
-        dumpUserFile(USER_10);
+        dumpUserFile(USER_11);
     }
 
     public void testShortcutInfoSaveAndLoad_maskableBitmap() throws InterruptedException {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
 
         final Icon bmp32x32 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
             getTestContext().getResources(), R.drawable.black_32x32));
@@ -1100,16 +1100,16 @@
         // Save and load.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
-        dumpUserFile(USER_10);
+        dumpUserFile(USER_11);
         dumpsysOnLogcat("after load");
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_11);
 
-        assertEquals(USER_10, si.getUserId());
-        assertEquals(HANDLE_USER_10, si.getUserHandle());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
@@ -1131,13 +1131,13 @@
         assertNull(si.getIconUri());
         assertTrue(si.getLastChangedTimestamp() < now);
 
-        dumpUserFile(USER_10);
+        dumpUserFile(USER_11);
     }
 
     public void testShortcutInfoSaveAndLoad_resId() throws InterruptedException {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
 
         final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32);
 
@@ -1175,13 +1175,13 @@
         // Save and load.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_11);
 
-        assertEquals(USER_10, si.getUserId());
-        assertEquals(HANDLE_USER_10, si.getUserHandle());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
@@ -1207,14 +1207,14 @@
 
         // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
         // to test it.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_11);
         assertEquals(1, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_uri() throws InterruptedException {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        setCaller(CALLING_PACKAGE_1, USER_10);
+        setCaller(CALLING_PACKAGE_1, USER_11);
 
         final Icon uriIcon = Icon.createWithContentUri("test_uri");
 
@@ -1255,13 +1255,13 @@
         // Save and load.
         mService.saveDirtyInfo();
         initService();
-        mService.handleUnlockUser(USER_10);
+        mService.handleUnlockUser(USER_11);
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_11);
 
-        assertEquals(USER_10, si.getUserId());
-        assertEquals(HANDLE_USER_10, si.getUserHandle());
+        assertEquals(USER_11, si.getUserId());
+        assertEquals(HANDLE_USER_11, si.getUserHandle());
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
         assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
@@ -1288,7 +1288,7 @@
 
         // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
         // to test it.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_11);
         assertEquals(1, si.getRank());
         assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_URI
                 | ShortcutInfo.FLAG_STRINGS_RESOLVED | ShortcutInfo.FLAG_ADAPTIVE_BITMAP,
@@ -1300,7 +1300,7 @@
     }
 
     public void testShortcutInfoSaveAndLoad_forBackup() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_32x32));
@@ -1332,16 +1332,16 @@
         mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         // Dynamic shortcuts won't be backed up, so we need to pin it.
-        setCaller(LAUNCHER_1, USER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
+        setCaller(LAUNCHER_1, USER_10);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_10);
 
         // Do backup & restore.
         backupAndRestore();
 
-        mService.handleUnlockUser(USER_0); // Load user-0.
+        mService.handleUnlockUser(USER_10); // Load user-0.
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
 
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
@@ -1364,12 +1364,12 @@
         assertNull(si.getIconUri());
 
         // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
         assertEquals(0, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_forBackup_resId() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32);
 
@@ -1399,16 +1399,16 @@
         mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         // Dynamic shortcuts won't be backed up, so we need to pin it.
-        setCaller(LAUNCHER_1, USER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
+        setCaller(LAUNCHER_1, USER_10);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_10);
 
         // Do backup & restore.
         backupAndRestore();
 
-        mService.handleUnlockUser(USER_0); // Load user-0.
+        mService.handleUnlockUser(USER_10); // Load user-0.
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
 
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
@@ -1434,12 +1434,12 @@
         assertNull(si.getIconUri());
 
         // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
         assertEquals(0, si.getRank());
     }
 
     public void testShortcutInfoSaveAndLoad_forBackup_uri() {
-        setCaller(CALLING_PACKAGE_1, USER_0);
+        setCaller(CALLING_PACKAGE_1, USER_10);
 
         final Icon uriIcon = Icon.createWithContentUri("test_uri");
 
@@ -1469,16 +1469,16 @@
         mManager.addDynamicShortcuts(list(sorig, sorig2));
 
         // Dynamic shortcuts won't be backed up, so we need to pin it.
-        setCaller(LAUNCHER_1, USER_0);
-        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
+        setCaller(LAUNCHER_1, USER_10);
+        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_10);
 
         // Do backup & restore.
         backupAndRestore();
 
-        mService.handleUnlockUser(USER_0); // Load user-0.
+        mService.handleUnlockUser(USER_10); // Load user-0.
 
         ShortcutInfo si;
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
 
         assertEquals(CALLING_PACKAGE_1, si.getPackage());
         assertEquals("id", si.getId());
@@ -1504,7 +1504,7 @@
         assertNull(si.getIconUri());
 
         // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
-        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
         assertEquals(0, si.getRank());
     }
 
@@ -1512,7 +1512,7 @@
         assertTrue(mManager.setDynamicShortcuts(list(
                 makeShortcutWithIntent("s1", intent))));
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         assertWith(getCallerShortcuts())
                 .haveIds("s1")
@@ -1528,7 +1528,7 @@
         assertTrue(mManager.setDynamicShortcuts(list(
                 makeShortcutWithIntents("s1", intents))));
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
         assertWith(getCallerShortcuts())
                 .haveIds("s1")
@@ -1804,35 +1804,35 @@
         // but it will work for other users too because we check the locale change at any
         // API entry point.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
 
         // Make sure even if we receive ACTION_LOCALE_CHANGED, if the locale hasn't actually
         // changed, we don't reset throttling.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             mManager.updateShortcuts(list());
             assertEquals(2, mManager.getRemainingCallCount());
         });
 
         mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
         });
 
@@ -1842,7 +1842,7 @@
         // The locale should be persisted, so it still shouldn't reset throttling.
         mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
         });
     }
@@ -1861,22 +1861,22 @@
 
         // First, all packages have less than 3 (== initial value) remaining calls.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
@@ -1886,22 +1886,22 @@
         mService.mUidObserver.onUidStateChanged(
                 CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
                 ActivityManager.PROCESS_CAPABILITY_NONE);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
@@ -1911,22 +1911,22 @@
         mService.mUidObserver.onUidStateChanged(
                 CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
                 ActivityManager.PROCESS_CAPABILITY_NONE);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         mService.mUidObserver.onUidStateChanged(
@@ -1944,22 +1944,22 @@
                 CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
                 ActivityManager.PROCESS_CAPABILITY_NONE);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
@@ -1967,7 +1967,7 @@
 
         // Do the same thing one more time.  This would catch the bug with mixuing up
         // the current time and the elapsed time.
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             mManager.updateShortcuts(list(makeShortcut("s")));
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
@@ -1979,22 +1979,22 @@
                 CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
                 ActivityManager.PROCESS_CAPABILITY_NONE);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
@@ -2003,10 +2003,10 @@
         // Package 1 on user-10 comes to foreground.
         // Now, also try calling some APIs and make sure foreground apps don't get throttled.
         mService.mUidObserver.onUidStateChanged(
-                UserHandle.getUid(USER_10, CALLING_UID_1),
+                UserHandle.getUid(USER_11, CALLING_UID_1),
                 ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
                 ActivityManager.PROCESS_CAPABILITY_NONE);
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
             assertFalse(mManager.isRateLimitingActive());
 
@@ -2025,7 +2025,7 @@
             assertEquals(0, mManager.getRemainingCallCount());
             assertTrue(mManager.isRateLimitingActive());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
 
             mManager.setDynamicShortcuts(list(makeShortcut("s")));
@@ -2035,7 +2035,7 @@
             assertEquals(0, mManager.getRemainingCallCount());
             assertTrue(mManager.isRateLimitingActive());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
 
             mManager.setDynamicShortcuts(list(makeShortcut("s")));
@@ -2045,7 +2045,7 @@
             assertEquals(0, mManager.getRemainingCallCount());
             assertTrue(mManager.isRateLimitingActive());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
 
             mManager.setDynamicShortcuts(list(makeShortcut("s")));
@@ -2065,7 +2065,7 @@
             assertEquals(0, mManager.getRemainingCallCount());
             assertTrue(mManager.isRateLimitingActive());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
 
             mManager.setDynamicShortcuts(list(makeShortcut("s")));
@@ -2088,95 +2088,95 @@
 
         // First, all packages have less than 3 (== initial value) remaining calls.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
 
         // Simulate a call from sys UI.
         mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
-        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0);
-
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertEquals(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-
-        mManager.onApplicationActive(CALLING_PACKAGE_3, USER_0);
-
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertEquals(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
-            assertEquals(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
-        });
-
         mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
-            assertEquals(3, mManager.getRemainingCallCount());
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
         });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+
+        mManager.onApplicationActive(CALLING_PACKAGE_3, USER_10);
+
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
+            assertEquals(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+
+        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_11);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertEquals(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_3, USER_10, () -> {
+            assertEquals(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_4, USER_10, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertEquals(3, mManager.getRemainingCallCount());
+        });
     }
 
     public void testReportShortcutUsed() {
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             reset(mMockUsageStatsManagerInternal);
 
             // Report with an nonexistent shortcut.
@@ -2192,9 +2192,9 @@
 
             mManager.reportShortcutUsed("s2");
             verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                    eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_10));
+                    eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_11));
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             // Try with a different package.
             reset(mMockUsageStatsManagerInternal);
 
@@ -2211,7 +2211,7 @@
 
             mManager.reportShortcutUsed("s3");
             verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
-                    eq(CALLING_PACKAGE_2), eq("s3"), eq(USER_10));
+                    eq(CALLING_PACKAGE_2), eq("s3"), eq(USER_11));
         });
     }
 
@@ -2333,7 +2333,7 @@
         final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource(
                 getTestContext().getResources(), R.drawable.black_64x64));
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithIcon("res32x32", res32x32),
                     makeShortcutWithIcon("res64x64", res64x64),
@@ -2342,9 +2342,9 @@
         });
 
         // We can't predict the compressed bitmap sizes, so get the real sizes here.
-        final long bitmapTotal =
-                new File(getBitmapAbsPath(USER_0, CALLING_PACKAGE_2, "bmp32x32")).length() +
-                new File(getBitmapAbsPath(USER_0, CALLING_PACKAGE_2, "bmp64x64")).length();
+        final long bitmapTotal = new File(getBitmapAbsPath(
+                USER_10, CALLING_PACKAGE_2, "bmp32x32")).length() + new File(
+                        getBitmapAbsPath(USER_10, CALLING_PACKAGE_2, "bmp64x64")).length();
 
         // Read the expected output and inject the bitmap size.
         final String expected = readTestAsset("shortcut/dumpsys_expected.txt")
@@ -2358,15 +2358,15 @@
      * can still be read.
      */
     public void testLoadLegacySavedFile() throws Exception {
-        final File path = mService.getUserFile(USER_0).getBaseFile();
+        final File path = mService.getUserFile(USER_10).getBaseFile();
         path.getParentFile().mkdirs();
         try (Writer w = new FileWriter(path)) {
             w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
         };
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("manifest-shortcut-storage")
                     .forShortcutWithId("manifest-shortcut-storage", si -> {
@@ -2381,58 +2381,58 @@
         mRunningUsers.clear();
         mUnlockedUsers.clear();
 
-        assertFalse(mService.isUserUnlockedL(USER_0));
         assertFalse(mService.isUserUnlockedL(USER_10));
+        assertFalse(mService.isUserUnlockedL(USER_11));
 
         // Start user 0, still locked.
-        mRunningUsers.put(USER_0, true);
-        assertFalse(mService.isUserUnlockedL(USER_0));
+        mRunningUsers.put(USER_10, true);
         assertFalse(mService.isUserUnlockedL(USER_10));
+        assertFalse(mService.isUserUnlockedL(USER_11));
 
         // Unlock user.
-        mUnlockedUsers.put(USER_0, true);
-        assertTrue(mService.isUserUnlockedL(USER_0));
-        assertFalse(mService.isUserUnlockedL(USER_10));
+        mUnlockedUsers.put(USER_10, true);
+        assertTrue(mService.isUserUnlockedL(USER_10));
+        assertFalse(mService.isUserUnlockedL(USER_11));
 
         // Clear again.
         mRunningUsers.clear();
         mUnlockedUsers.clear();
 
         // Directly call the lifecycle event.  Now also locked.
-        mService.handleUnlockUser(USER_0);
-        assertTrue(mService.isUserUnlockedL(USER_0));
-        assertFalse(mService.isUserUnlockedL(USER_10));
+        mService.handleUnlockUser(USER_10);
+        assertTrue(mService.isUserUnlockedL(USER_10));
+        assertFalse(mService.isUserUnlockedL(USER_11));
 
         // Directly call the stop lifecycle event.  Goes back to the initial state.
-        mService.handleStopUser(USER_0);
-        assertFalse(mService.isUserUnlockedL(USER_0));
+        mService.handleStopUser(USER_10);
         assertFalse(mService.isUserUnlockedL(USER_10));
+        assertFalse(mService.isUserUnlockedL(USER_11));
     }
 
     public void testEphemeralApp() {
-        mRunningUsers.put(USER_10, true); // this test needs user 10.
+        mRunningUsers.put(USER_11, true); // this test needs user 10.
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertWith(mManager.getDynamicShortcuts()).isEmpty();
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(mManager.getDynamicShortcuts()).isEmpty();
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertWith(mManager.getDynamicShortcuts()).isEmpty();
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(mManager.getDynamicShortcuts()).isEmpty();
         });
         // Make package 1 ephemeral.
-        mEphemeralPackages.add(UserPackage.of(USER_0, CALLING_PACKAGE_1));
+        mEphemeralPackages.add(UserPackage.of(USER_10, CALLING_PACKAGE_1));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertExpectException(IllegalStateException.class, "Ephemeral apps", () -> {
                 mManager.getDynamicShortcuts();
             });
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(mManager.getDynamicShortcuts()).isEmpty();
         });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             assertWith(mManager.getDynamicShortcuts()).isEmpty();
         });
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
index 43e527c..aad06c6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -70,14 +70,14 @@
                 + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
         );
 
-        setCaller(CALLING_PACKAGE, USER_0);
+        setCaller(CALLING_PACKAGE, USER_10);
     }
 
     private void publishManifestShortcuts(ComponentName activity, int resId) {
         addManifestShortcutResource(activity, resId);
         updatePackageVersion(CALLING_PACKAGE, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE, USER_10));
     }
 
     public void testSetDynamicShortcuts_noManifestShortcuts() {
@@ -299,8 +299,8 @@
                 .isEmpty();
 
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_10);
         });
         // Still same order.
         assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
@@ -408,9 +408,9 @@
         assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
                 .isEmpty();
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(
-                    CALLING_PACKAGE, list("s2", "s4", "x1", "x2"), HANDLE_USER_0);
+                    CALLING_PACKAGE, list("s2", "s4", "x1", "x2"), HANDLE_USER_10);
         });
         // Still same order.
 
@@ -483,8 +483,8 @@
         assertWith(getCallerShortcuts()).selectDynamic().selectByChangedSince(lastApiTime)
                 .haveIds("s2", "s4");
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_0);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE, list("s2", "s4", "x2"), HANDLE_USER_10);
         });
         // Still same order.
         assertWith(getCallerShortcuts()).selectDynamic().selectByActivity(A1)
@@ -518,7 +518,7 @@
                 R.xml.shortcut_share_targets);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
 
         // There are two valid <share-target> definitions in the test manifest with two different
         // categories: {"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"} and
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
index 11a2a8a..42c1767 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -116,7 +116,7 @@
         final Intent intent = new Intent(Intent.ACTION_MAIN)
                 .putExtras(sIntentExtras);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcutWithExtras("s1", intent, sShortcutExtras),
                     makeShortcut("s{\u0000}{\u0001}{\uD800\uDC00}x[\uD801][\uDC01]")
@@ -125,9 +125,9 @@
 
         // Make sure save & load works fine. (i.e. shouldn't crash even with invalid characters.)
         initService();
-        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_10);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("s1", "s{\u0000}{\u0001}{\uD800\uDC00}x[?][?]")
                     .forShortcutWithId("s1", si -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
index 6c10bfd..7f7a4ae 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
@@ -28,52 +28,7 @@
 public class ShortcutManagerTest6 extends BaseShortcutManagerTest {
     public void testHasShortcutHostPermissionInner_with3pLauncher_complicated() {
         // Set the default launcher.
-        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_2, USER_0);
-        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
-        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
-        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
-        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
-
-        // Last known launcher should be set.
-        assertEquals(CALLING_PACKAGE_2,
-                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
-
-        // Now the default launcher has changed.
-        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_1, USER_0);
-
-        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
-
-        // Last known launcher should be set.
-        assertEquals(CALLING_PACKAGE_1,
-                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
-
-        // Change the default launcher again.
-        prepareGetRoleHoldersAsUser(
-                getSystemLauncher().activityInfo.getComponentName().getPackageName(), USER_0);
-
-        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
-        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
-
-        // Last known launcher should be set to default.
-        assertEquals(PACKAGE_SYSTEM_LAUNCHER,
-                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
-    }
-
-    public void testHasShortcutHostPermissionInner_multiUser() {
-        mRunningUsers.put(USER_10, true);
-
-        prepareGetRoleHoldersAsUser(PACKAGE_FALLBACK_LAUNCHER, USER_0);
         prepareGetRoleHoldersAsUser(CALLING_PACKAGE_2, USER_10);
-
-        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_0));
-        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_0));
-        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_0));
-        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_0));
-
-        // Last known launcher should be set.
-        assertEquals(PACKAGE_FALLBACK_LAUNCHER,
-                mService.getUserShortcutsLocked(USER_0).getCachedLauncher());
-
         assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_10));
         assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_10));
         assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_10));
@@ -82,5 +37,50 @@
         // Last known launcher should be set.
         assertEquals(CALLING_PACKAGE_2,
                 mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+        // Now the default launcher has changed.
+        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_1, USER_10);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_10));
+
+        // Last known launcher should be set.
+        assertEquals(CALLING_PACKAGE_1,
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+        // Change the default launcher again.
+        prepareGetRoleHoldersAsUser(
+                getSystemLauncher().activityInfo.getComponentName().getPackageName(), USER_10);
+
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_10));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_10));
+
+        // Last known launcher should be set to default.
+        assertEquals(PACKAGE_SYSTEM_LAUNCHER,
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+    }
+
+    public void testHasShortcutHostPermissionInner_multiUser() {
+        mRunningUsers.put(USER_11, true);
+
+        prepareGetRoleHoldersAsUser(PACKAGE_FALLBACK_LAUNCHER, USER_10);
+        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_2, USER_11);
+
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_10));
+        assertTrue(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_10));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_10));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_10));
+
+        // Last known launcher should be set.
+        assertEquals(PACKAGE_FALLBACK_LAUNCHER,
+                mService.getUserShortcutsLocked(USER_10).getCachedLauncher());
+
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_SYSTEM_LAUNCHER, USER_11));
+        assertFalse(mService.hasShortcutHostPermissionInner(PACKAGE_FALLBACK_LAUNCHER, USER_11));
+        assertFalse(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_1, USER_11));
+        assertTrue(mService.hasShortcutHostPermissionInner(CALLING_PACKAGE_2, USER_11));
+
+        // Last known launcher should be set.
+        assertEquals(CALLING_PACKAGE_2,
+                mService.getUserShortcutsLocked(USER_11).getCachedLauncher());
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index 161b18c..86bde83 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -131,20 +131,20 @@
     public void testResetThrottling() throws Exception {
         prepareCrossProfileDataSet();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
 
         mInjectedCallingUid = Process.SHELL_UID;
-        assertSuccess(callShellCommand("reset-throttling"));
+        assertSuccess(callShellCommand("reset-throttling", "--user", "10"));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
     }
@@ -152,27 +152,27 @@
     public void testResetThrottling_user_not_running() throws Exception {
         prepareCrossProfileDataSet();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
 
         mInjectedCallingUid = Process.SHELL_UID;
 
-        mRunningUsers.put(USER_10, false);
+        mRunningUsers.put(USER_11, false);
 
         assertTrue(resultContains(
-                callShellCommand("reset-throttling", "--user", "10"),
-                "User (with userId=10) is not running or locked"));
+                callShellCommand("reset-throttling", "--user", "11"),
+                "User (with userId=11) is not running or locked"));
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
     }
@@ -180,23 +180,23 @@
     public void testResetThrottling_user_running() throws Exception {
         prepareCrossProfileDataSet();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.getRemainingCallCount() < 3);
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertTrue(mManager.getRemainingCallCount() < 3);
+        });
 
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
 
         mInjectedCallingUid = Process.SHELL_UID;
-        assertSuccess(callShellCommand("reset-throttling", "--user", "10"));
+        assertSuccess(callShellCommand("reset-throttling", "--user", "11"));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
     }
@@ -204,81 +204,81 @@
     public void testResetAllThrottling() throws Exception {
         prepareCrossProfileDataSet();
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.getRemainingCallCount() < 3);
         });
 
         mInjectedCallingUid = Process.SHELL_UID;
         assertSuccess(callShellCommand("reset-all-throttling"));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertEquals(3, mManager.getRemainingCallCount());
         });
     }
 
     // This command is deprecated. Will remove the test later.
     public void testLauncherCommands() throws Exception {
-        prepareGetRoleHoldersAsUser(getSystemLauncher().activityInfo.packageName, USER_0);
+        prepareGetRoleHoldersAsUser(getSystemLauncher().activityInfo.packageName, USER_10);
         prepareGetHomeActivitiesAsUser(
                 /* preferred */ getSystemLauncher().activityInfo.getComponentName(),
                 list(getSystemLauncher(), getFallbackLauncher()),
-                USER_0);
+                USER_10);
 
-        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_2, USER_10);
+        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_2, USER_11);
         prepareGetHomeActivitiesAsUser(
                 /* preferred */ cn(CALLING_PACKAGE_2, "name"),
                 list(getSystemLauncher(), getFallbackLauncher(),
                         ri(CALLING_PACKAGE_1, "name", false, 0),
                         ri(CALLING_PACKAGE_2, "name", false, 0)
                 ),
-                USER_10);
+                USER_11);
 
         // First, test "get".
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
         mInjectedCallingUid = Process.SHELL_UID;
         assertContains(
-                assertSuccess(callShellCommand("get-default-launcher")),
+                assertSuccess(callShellCommand("get-default-launcher", "--user", "10")),
                 "Launcher: ComponentInfo{com.android.systemlauncher/systemlauncher_name}");
 
         assertContains(
-                assertSuccess(callShellCommand("get-default-launcher", "--user", "10")),
+                assertSuccess(callShellCommand("get-default-launcher", "--user", "11")),
                 "Launcher: ComponentInfo{com.android.test.2/name}");
 
         // Change user-0's launcher.
-        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_1, USER_0);
+        prepareGetRoleHoldersAsUser(CALLING_PACKAGE_1, USER_10);
         prepareGetHomeActivitiesAsUser(
                 /* preferred */ cn(CALLING_PACKAGE_1, "name"),
                 list(ri(CALLING_PACKAGE_1, "name", false, 0)),
-                USER_0);
+                USER_10);
         assertContains(
-                assertSuccess(callShellCommand("get-default-launcher")),
+                assertSuccess(callShellCommand("get-default-launcher", "--user", "10")),
                 "Launcher: ComponentInfo{com.android.test.1/name}");
     }
 
     public void testUnloadUser() throws Exception {
         prepareCrossProfileDataSet();
 
-        assertNotNull(mService.getShortcutsForTest().get(USER_10));
+        assertNotNull(mService.getShortcutsForTest().get(USER_11));
 
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
 
         mInjectedCallingUid = Process.SHELL_UID;
-        assertSuccess(callShellCommand("unload-user", "--user", "10"));
+        assertSuccess(callShellCommand("unload-user", "--user", "11"));
 
-        assertNull(mService.getShortcutsForTest().get(USER_10));
+        assertNull(mService.getShortcutsForTest().get(USER_11));
     }
 
     public void testClearShortcuts() throws Exception {
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         // Add two manifests and two dynamics.
         addManifestShortcutResource(
@@ -286,17 +286,17 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_11);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "s1", "s2")
                     .areAllEnabled()
@@ -307,14 +307,14 @@
 
         // First, call for a different package.
 
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
 
         mInjectedCallingUid = Process.SHELL_UID;
-        assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_2));
+        assertSuccess(callShellCommand("clear-shortcuts", "--user", "11", CALLING_PACKAGE_2));
 
         // Shouldn't be cleared yet.
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "s1", "s2")
                     .areAllEnabled()
@@ -324,10 +324,10 @@
         });
 
         mInjectedCallingUid = Process.SHELL_UID;
-        assertSuccess(callShellCommand("clear-shortcuts", "--user", "10", CALLING_PACKAGE_1));
+        assertSuccess(callShellCommand("clear-shortcuts", "--user", "11", CALLING_PACKAGE_1));
 
         // Only manifest shortcuts will remain, and are no longer pinned.
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2")
                     .areAllEnabled()
@@ -337,7 +337,7 @@
 
     public void testGetShortcuts() throws Exception {
 
-        mRunningUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
 
         // Add two manifests and two dynamics.
         addManifestShortcutResource(
@@ -345,20 +345,20 @@
                 R.xml.shortcut_2);
         updatePackageVersion(CALLING_PACKAGE_1, 1);
         mService.mPackageMonitor.onReceive(getTestContext(),
-                genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_11));
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.addDynamicShortcuts(list(
                     makeLongLivedShortcut("s1"), makeShortcut("s2"))));
         });
-        runWithCaller(LAUNCHER_1, USER_10, () -> {
+        runWithCaller(LAUNCHER_1, USER_11, () -> {
             mInjectCheckAccessShortcutsPermission = true;
-            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_10,
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_11,
                     CACHE_OWNER);
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_11);
         });
 
-        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertWith(getCallerShortcuts())
                     .haveIds("ms1", "ms2", "s1", "s2")
                     .areAllEnabled()
@@ -368,33 +368,33 @@
         });
 
 
-        mRunningUsers.put(USER_10, true);
-        mUnlockedUsers.put(USER_10, true);
+        mRunningUsers.put(USER_11, true);
+        mUnlockedUsers.put(USER_11, true);
 
         mInjectedCallingUid = Process.SHELL_UID;
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_CACHED), CALLING_PACKAGE_1),
                 "s1");
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_DYNAMIC), CALLING_PACKAGE_1),
                 "s1", "s2");
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_MANIFEST), CALLING_PACKAGE_1),
                 "ms1", "ms2");
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_PINNED), CALLING_PACKAGE_1),
                 "ms2", "s2");
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_DYNAMIC
                         | ShortcutManager.FLAG_MATCH_PINNED), CALLING_PACKAGE_1),
                 "ms2", "s1", "s2");
 
-        assertHaveIds(callShellCommand("get-shortcuts", "--user", "10", "--flags",
+        assertHaveIds(callShellCommand("get-shortcuts", "--user", "11", "--flags",
                 Integer.toString(ShortcutManager.FLAG_MATCH_MANIFEST
                         | ShortcutManager.FLAG_MATCH_CACHED), CALLING_PACKAGE_1),
                 "ms1", "ms2", "s1");
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index a85c722..9b02a3a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -85,32 +85,32 @@
     }
 
     public void testGetParentOrSelfUserId() {
-        assertEquals(USER_0, mService.getParentOrSelfUserId(USER_0));
         assertEquals(USER_10, mService.getParentOrSelfUserId(USER_10));
         assertEquals(USER_11, mService.getParentOrSelfUserId(USER_11));
-        assertEquals(USER_0, mService.getParentOrSelfUserId(USER_P0));
+        assertEquals(USER_12, mService.getParentOrSelfUserId(USER_12));
+        assertEquals(USER_10, mService.getParentOrSelfUserId(USER_P0));
     }
 
     public void testIsRequestPinShortcutSupported() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        setDefaultLauncher(USER_10, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        setDefaultLauncher(USER_11, LAUNCHER_2);
 
         Pair<ComponentName, Integer> actual;
         // User 0
-        actual = mProcessor.getRequestPinConfirmationActivity(USER_0,
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
                 PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_1, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
-        assertEquals(USER_0, (int) actual.second);
+        assertEquals(USER_10, (int) actual.second);
 
         // User 10
-        actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_11,
                 PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_2, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
-        assertEquals(USER_10, (int) actual.second);
+        assertEquals(USER_11, (int) actual.second);
 
         // User P0 -> managed profile, return user-0's launcher.
         actual = mProcessor.getRequestPinConfirmationActivity(USER_P0,
@@ -118,18 +118,18 @@
 
         assertEquals(LAUNCHER_1, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
-        assertEquals(USER_0, (int) actual.second);
+        assertEquals(USER_10, (int) actual.second);
 
         // Check from the public API.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.isRequestPinShortcutSupported());
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.isRequestPinShortcutSupported());
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             assertTrue(mManager.isRequestPinShortcutSupported());
         });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            assertTrue(mManager.isRequestPinShortcutSupported());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
+            assertTrue(mManager.isRequestPinShortcutSupported());
+        });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.isRequestPinShortcutSupported());
         });
@@ -140,27 +140,27 @@
                         ? null : new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
 
         // User 10 -- still has confirm activity.
-        actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_11,
                 PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_2, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
-        assertEquals(USER_10, (int) actual.second);
+        assertEquals(USER_11, (int) actual.second);
 
         // But user-0 and user p0 no longer has a confirmation activity.
-        assertNull(mProcessor.getRequestPinConfirmationActivity(USER_0,
+        assertNull(mProcessor.getRequestPinConfirmationActivity(USER_10,
                 PinItemRequest.REQUEST_TYPE_SHORTCUT));
         assertNull(mProcessor.getRequestPinConfirmationActivity(USER_P0,
                 PinItemRequest.REQUEST_TYPE_SHORTCUT));
 
         // Check from the public API.
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertFalse(mManager.isRequestPinShortcutSupported());
-        });
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertFalse(mManager.isRequestPinShortcutSupported());
-        });
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertFalse(mManager.isRequestPinShortcutSupported());
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+            assertFalse(mManager.isRequestPinShortcutSupported());
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_11, () -> {
             assertTrue(mManager.isRequestPinShortcutSupported());
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -170,13 +170,13 @@
 
     public void testRequestPinShortcut_notSupported() {
         // User-0's launcher has no confirmation activity.
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         mPinConfirmActivityFetcher = (packageName, userId) ->
                 !LAUNCHER_2.equals(packageName)
                         ? null : new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
 
-        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
 
             assertFalse(mManager.requestPinShortcut(s1,
@@ -188,7 +188,7 @@
                     .sendIntentSender(any(IntentSender.class));
         });
 
-        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
 
             assertFalse(mManager.requestPinShortcut(s1,
@@ -223,7 +223,7 @@
     }
 
     public void testNotForeground() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             makeCallerBackground();
@@ -252,8 +252,8 @@
      * - Shortcut doesn't pre-exist.
      */
     private void checkRequestPinShortcut(@Nullable IntentSender resultIntent) {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        setDefaultLauncher(USER_10, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        setDefaultLauncher(USER_11, LAUNCHER_2);
 
         final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
 
@@ -276,11 +276,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -337,8 +337,8 @@
     }
 
     public void testRequestPinShortcut_explicitTargetActivity() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        setDefaultLauncher(USER_10, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        setDefaultLauncher(USER_11, LAUNCHER_2);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcutWithActivity("s1",
@@ -353,11 +353,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -393,7 +393,7 @@
     }
 
     public void testRequestPinShortcut_wrongTargetActivity() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             // Create dynamic shortcut
@@ -411,8 +411,8 @@
     }
 
     public void testRequestPinShortcut_noTargetActivity_noMainActivity() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        setDefaultLauncher(USER_10, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        setDefaultLauncher(USER_11, LAUNCHER_2);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             /// Create a shortcut with no target activity.
@@ -435,11 +435,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -476,7 +476,7 @@
     }
 
     public void testRequestPinShortcut_dynamicExists() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
 
@@ -497,11 +497,11 @@
                     .areAllNotPinned();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -534,7 +534,7 @@
     }
 
     public void testRequestPinShortcut_manifestExists() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
@@ -552,11 +552,11 @@
                     .areAllNotPinned();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -591,7 +591,7 @@
     }
 
     public void testRequestPinShortcut_dynamicExists_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
 
@@ -604,7 +604,7 @@
             assertTrue(mManager.setDynamicShortcuts(list(s)));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
@@ -633,11 +633,11 @@
         });
 
         // ... But the launcher will still receive the request.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -676,13 +676,13 @@
     }
 
     public void testRequestPinShortcut_manifestExists_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_P0);
         });
 
@@ -713,11 +713,11 @@
         });
 
         // ... But the launcher will still receive the request.
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -758,13 +758,13 @@
     }
 
     public void testRequestPinShortcut_wasDynamic_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
@@ -786,13 +786,13 @@
     }
 
     public void testRequestPinShortcut_wasDynamic_disabled_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
@@ -817,13 +817,13 @@
     }
 
     public void testRequestPinShortcut_wasManifest_alreadyPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_P0);
         });
 
@@ -855,11 +855,11 @@
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
         });
 
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertWith(getCallerShortcuts())
@@ -876,11 +876,11 @@
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -917,11 +917,11 @@
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
         });
 
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_P0);
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertWith(getCallerShortcuts())
@@ -939,11 +939,11 @@
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -980,13 +980,13 @@
      * the existing one.
      */
     public void testRequestPinShortcut_launcherAlreadyHasPinned() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"), makeShortcut("s2"))));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_P0);
         });
 
@@ -997,11 +997,11 @@
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1042,7 +1042,7 @@
      * When trying to pin an existing shortcut, the new fields shouldn't override existing fields.
      */
     public void testRequestPinShortcut_dynamicExists_titleWontChange() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
 
@@ -1063,11 +1063,11 @@
                     .areAllNotPinned();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1107,7 +1107,7 @@
      * When trying to pin an existing shortcut, the new fields shouldn't override existing fields.
      */
     public void testRequestPinShortcut_manifestExists_titleWontChange() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
@@ -1125,11 +1125,11 @@
                     .areAllNotPinned();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1174,7 +1174,7 @@
      * has a partial shortcut, accept() should fail.
      */
     public void testRequestPinShortcut_dynamicExists_thenRemoved_error() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             // Create dynamic shortcut
@@ -1192,11 +1192,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1232,7 +1232,7 @@
      * has all the mandatory fields, we can go ahead and still publish it.
      */
     public void testRequestPinShortcut_dynamicExists_thenRemoved_okay() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             // Create dynamic shortcut
@@ -1250,11 +1250,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1288,7 +1288,7 @@
      * has a partial shortcut, accept() should fail.
      */
     public void testRequestPinShortcut_manifestExists_thenRemoved_error() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
@@ -1304,11 +1304,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1345,7 +1345,7 @@
      * has all the mandatory fields, we can go ahead and still publish it.
      */
     public void testRequestPinShortcut_manifestExists_thenRemoved_okay() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
@@ -1361,11 +1361,11 @@
                     .isEmpty();
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1405,7 +1405,7 @@
      * has a partial shortcut, accept() should fail.
      */
     public void testRequestPinShortcut_dynamicExists_thenDisabled_error() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
@@ -1419,8 +1419,8 @@
 
         // Then, pin by another launcher and disable it.
         // We have to pin it here so that disable() won't remove it.
-        setDefaultLauncher(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        setDefaultLauncher(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_P0);
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1431,12 +1431,12 @@
                     .areAllDisabled();
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1479,7 +1479,7 @@
      * has a partial shortcut, accept() should fail.
      */
     public void testRequestPinShortcut_manifestExists_thenDisabled_error() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             publishManifestShortcutsAsCaller(R.xml.shortcut_1);
@@ -1492,8 +1492,8 @@
 
         // Then, pin by another launcher and disable it.
         // We have to pin it here so that disable() won't remove it.
-        setDefaultLauncher(USER_0, LAUNCHER_2);
-        runWithCaller(LAUNCHER_2, USER_0, () -> {
+        setDefaultLauncher(USER_10, LAUNCHER_2);
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1"), HANDLE_USER_P0);
         });
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -1505,12 +1505,12 @@
                     .areAllDisabled();
         });
 
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
@@ -1551,7 +1551,7 @@
     }
 
     public void testRequestPinShortcut_wrongLauncherCannotAccept() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             ShortcutInfo s1 = makeShortcut("s1");
@@ -1560,11 +1560,11 @@
         });
 
         final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
-        verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+        verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
         final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue());
 
         // Verify that other launcher can't use this request
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Set some random caller UID.
             mInjectedCallingUid = 12345;
 
@@ -1573,7 +1573,7 @@
         });
 
         // The default launcher can still use this request
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             assertTrue(request.isValid());
             assertTrue(request.accept());
         });
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 2fca3d0..ee1bf38 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -91,7 +91,7 @@
     }
 
     public void testNotForeground() {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             makeCallerBackground();
@@ -108,8 +108,8 @@
     }
 
     private void checkRequestPinAppWidget(@Nullable PendingIntent resultIntent) {
-        setDefaultLauncher(USER_0, LAUNCHER_1);
-        setDefaultLauncher(USER_10, LAUNCHER_2);
+        setDefaultLauncher(USER_10, LAUNCHER_1);
+        setDefaultLauncher(USER_11, LAUNCHER_2);
 
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
             AppWidgetProviderInfo info = makeProviderInfo("c1");
@@ -120,11 +120,11 @@
             verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class));
         });
 
-        runWithCaller(LAUNCHER_1, USER_0, () -> {
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
             // Check the intent passed to startActivityAsUser().
             final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
 
-            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0));
+            verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_10));
 
             assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage);
 
diff --git a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java
index b1df0f1..c7a06b8 100644
--- a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java
@@ -31,6 +31,7 @@
 import android.os.test.TestLooper;
 import android.provider.Settings;
 import android.security.advancedprotection.AdvancedProtectionFeature;
+import android.security.advancedprotection.AdvancedProtectionManager;
 import android.security.advancedprotection.IAdvancedProtectionCallback;
 
 import androidx.annotation.NonNull;
@@ -54,7 +55,8 @@
     private Context mContext;
     private AdvancedProtectionService.AdvancedProtectionStore mStore;
     private TestLooper mLooper;
-    AdvancedProtectionFeature mFeature = new AdvancedProtectionFeature("test-id");
+    AdvancedProtectionFeature mTestFeature2g = new AdvancedProtectionFeature(
+            AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G);
 
     @Before
     public void setup() throws Settings.SettingNotFoundException {
@@ -105,7 +107,7 @@
                     @NonNull
                     @Override
                     public AdvancedProtectionFeature getFeature() {
-                        return mFeature;
+                        return mTestFeature2g;
                     }
 
                     @Override
@@ -135,7 +137,7 @@
                     @NonNull
                     @Override
                     public AdvancedProtectionFeature getFeature() {
-                        return mFeature;
+                        return mTestFeature2g;
                     }
 
                     @Override
@@ -165,7 +167,7 @@
                     @NonNull
                     @Override
                     public AdvancedProtectionFeature getFeature() {
-                        return mFeature;
+                        return mTestFeature2g;
                     }
 
                     @Override
@@ -238,8 +240,10 @@
 
     @Test
     public void testGetFeatures() {
-        AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature("id-1");
-        AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature("id-2");
+        AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature(
+                AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G);
+        AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature(
+                AdvancedProtectionManager.FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES);
         AdvancedProtectionHook hook = new AdvancedProtectionHook(mContext, true) {
             @NonNull
             @Override
@@ -268,8 +272,10 @@
 
     @Test
     public void testGetFeatures_featureNotAvailable() {
-        AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature("id-1");
-        AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature("id-2");
+        AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature(
+                AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G);
+        AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature(
+                AdvancedProtectionManager.FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES);
         AdvancedProtectionHook hook = new AdvancedProtectionHook(mContext, true) {
             @NonNull
             @Override
diff --git a/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java b/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java
index 9c61d95..9528a05 100644
--- a/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/CacheQuotaStrategyTest.java
@@ -23,13 +23,13 @@
 import android.util.Pair;
 import android.util.Xml;
 
-import com.android.internal.util.FastXmlSerializer;
 import com.android.modules.utils.TypedXmlSerializer;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.ByteArrayInputStream;
 import java.io.StringWriter;
@@ -123,8 +123,24 @@
                 buildCacheQuotaHint("uuid2", 10, 250));
     }
 
+    @Test
+    public void testReadInvalidInput() throws Exception {
+        String input = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" +
+                "<cache-info previousBytes=\"1000\">\n"
+                + "<quota/>\n"
+                + "</cache-info>\n";
+
+        try {
+            CacheQuotaStrategy.readFromXml(new ByteArrayInputStream(
+                    input.getBytes("UTF-8")));
+            fail("Expected XML parsing exception");
+        } catch (XmlPullParserException e) {
+            // Expected XmlPullParserException exception
+        }
+    }
+
     private CacheQuotaHint buildCacheQuotaHint(String volumeUuid, int uid, long quota) {
         return new CacheQuotaHint.Builder()
                 .setVolumeUuid(volumeUuid).setUid(uid).setQuota(quota).build();
     }
-}
\ No newline at end of file
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index decbaac..d1dc8d6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -274,6 +274,7 @@
         assertEquals(new ArraySet<>(), approved.get(true));
     }
 
+    @SuppressWarnings("GuardedBy")
     @Test
     public void testReadXml_userDisabled_restore() throws Exception {
         String xml = "<enabled_assistants version=\"4\" defaults=\"b/b\">"
@@ -289,7 +290,8 @@
         mAssistants.readXml(parser, mNm::canUseManagedServices, true,
                 ActivityManager.getCurrentUser());
 
-        ArrayMap<Boolean, ArraySet<String>> approved = mAssistants.mApproved.get(0);
+        ArrayMap<Boolean, ArraySet<String>> approved = mAssistants.mApproved.get(
+                ActivityManager.getCurrentUser());
 
         // approved should not be null
         assertNotNull(approved);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 20f4bb6..601023f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -17683,4 +17683,145 @@
 
         assertThat(mService.mNotificationList).isEmpty();
     }
+
+    @Test
+    @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+            FLAG_NOTIFICATION_FORCE_GROUPING,
+            FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
+    public void testUnbundleNotification_ungrouped_restoresOriginalChannel() throws Exception {
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+        when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+        when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+        when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+        when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+
+        // Post a single notification
+        final boolean hasOriginalSummary = false;
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        final String keyToUnbundle = r.getKey();
+        mService.addNotification(r);
+
+        // Classify notification into the NEWS bundle
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_TYPE, Adjustment.TYPE_NEWS);
+        Adjustment adjustment = new Adjustment(
+                r.getSbn().getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier());
+        mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+        waitForIdle();
+        r.applyAdjustments();
+        // Check that the NotificationRecord channel is updated
+        assertThat(r.getChannel().getId()).isEqualTo(NEWS_ID);
+        // Check that the Notification mChannelId is not updated
+        assertThat(r.getNotification().getChannelId()).isEqualTo(TEST_CHANNEL_ID);
+
+        // Unbundle the notification
+        mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+
+        // Check that the original channel was restored
+        assertThat(r.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+        verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(r), eq(hasOriginalSummary));
+    }
+
+    @Test
+    @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+            FLAG_NOTIFICATION_FORCE_GROUPING,
+            FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
+    public void testUnbundleNotification_grouped_restoresOriginalChannel() throws Exception {
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+        when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+        when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+        when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+        when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+
+        // Post grouped notifications
+        final String originalGroupName = "originalGroup";
+        final int summaryId = 0;
+        final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel,
+                summaryId + 1, originalGroupName, false);
+        mService.addNotification(r1);
+        final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel,
+                summaryId + 2, originalGroupName, false);
+        mService.addNotification(r2);
+        final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel,
+                summaryId, originalGroupName, true);
+        mService.addNotification(summary);
+        final String originalGroupKey = summary.getGroupKey();
+        assertThat(mService.mSummaryByGroupKey).containsEntry(originalGroupKey, summary);
+
+        // Classify a child notification into the NEWS bundle
+        final String keyToUnbundle = r1.getKey();
+        final boolean hasOriginalSummary = true;
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_TYPE, Adjustment.TYPE_NEWS);
+        Adjustment adjustment = new Adjustment(r1.getSbn().getPackageName(), r1.getKey(), signals,
+                "", r1.getUser().getIdentifier());
+        mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+        waitForIdle();
+        r1.applyAdjustments();
+        assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID);
+
+        // Unbundle the notification
+        mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+
+        // Check that the original channel was restored
+        assertThat(r1.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+        verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(r1), eq(hasOriginalSummary));
+    }
+
+    @Test
+    @EnableFlags({FLAG_NOTIFICATION_CLASSIFICATION,
+        FLAG_NOTIFICATION_FORCE_GROUPING,
+        FLAG_NOTIFICATION_REGROUP_ON_CLASSIFICATION})
+    public void testUnbundleNotification_groupedSummaryCanceled_restoresOriginalChannel()
+            throws Exception {
+        NotificationManagerService.WorkerHandler handler = mock(
+                NotificationManagerService.WorkerHandler.class);
+        mService.setHandler(handler);
+        when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true);
+        when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
+        when(mAssistants.isAdjustmentKeyTypeAllowed(anyInt())).thenReturn(true);
+        when(mAssistants.isTypeAdjustmentAllowedForPackage(anyString())).thenReturn(true);
+
+        // Post grouped notifications
+        final String originalGroupName = "originalGroup";
+        final int summaryId = 0;
+        final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel,
+                summaryId + 1, originalGroupName, false);
+        mService.addNotification(r1);
+        final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel,
+                summaryId + 2, originalGroupName, false);
+        mService.addNotification(r2);
+        final NotificationRecord summary = generateNotificationRecord(mTestNotificationChannel,
+                summaryId, originalGroupName, true);
+        mService.addNotification(summary);
+        final String originalGroupKey = summary.getGroupKey();
+        assertThat(mService.mSummaryByGroupKey).containsEntry(originalGroupKey, summary);
+
+        // Classify a child notification into the NEWS bundle
+        final String keyToUnbundle = r1.getKey();
+        Bundle signals = new Bundle();
+        signals.putInt(Adjustment.KEY_TYPE, Adjustment.TYPE_NEWS);
+        Adjustment adjustment = new Adjustment(r1.getSbn().getPackageName(), r1.getKey(), signals,
+                "", r1.getUser().getIdentifier());
+        mBinderService.applyAdjustmentFromAssistant(null, adjustment);
+        waitForIdle();
+        r1.applyAdjustments();
+        assertThat(r1.getChannel().getId()).isEqualTo(NEWS_ID);
+
+        // Cancel original summary
+        final boolean hasOriginalSummary = false;
+        mService.mSummaryByGroupKey.remove(summary.getGroupKey());
+
+        // Unbundle the notification
+        mService.mNotificationDelegate.unbundleNotification(keyToUnbundle);
+
+        // Check that the original channel was restored
+        assertThat(r1.getChannel().getId()).isEqualTo(TEST_CHANNEL_ID);
+        verify(mGroupHelper, times(1)).onNotificationUnbundled(eq(r1), eq(hasOriginalSummary));
+    }
+
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index fbd53f7..8e79514 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -66,7 +66,6 @@
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED;
 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED;
-import static com.android.server.notification.Flags.FLAG_ALL_NOTIFS_NEED_TTL;
 import static com.android.server.notification.Flags.FLAG_NOTIFICATION_VERIFY_CHANNEL_SOUND_URI;
 import static com.android.server.notification.Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA;
 import static com.android.server.notification.NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER;
@@ -155,7 +154,6 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
 import com.android.internal.config.sysui.TestableFlagResolver;
@@ -167,9 +165,6 @@
 import com.android.server.UiServiceTestCase;
 import com.android.server.notification.PermissionHelper.PackagePermission;
 
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.protobuf.InvalidProtocolBufferException;
@@ -204,6 +199,9 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ThreadLocalRandom;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4.class)
 @EnableFlags(FLAG_PERSIST_INCOMPLETE_RESTORE_DATA)
@@ -2640,6 +2638,35 @@
     }
 
     @Test
+    public void getPackagesBypassingDnd_multipleUsers() {
+        int uidUser1 = UserHandle.getUid(1, UID_P);
+        NotificationChannel channelUser1Bypass = new NotificationChannel("id11", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channelUser1Bypass.setBypassDnd(true);
+        NotificationChannel channelUser1NoBypass = new NotificationChannel("id12", "name2",
+                NotificationManager.IMPORTANCE_MAX);
+        channelUser1NoBypass.setBypassDnd(false);
+
+        int uidUser2 = UserHandle.getUid(2, UID_P);
+        NotificationChannel channelUser2Bypass = new NotificationChannel("id21", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channelUser2Bypass.setBypassDnd(true);
+
+        mHelper.createNotificationChannel(PKG_P, uidUser1, channelUser1Bypass, true,
+                /* hasDndAccess= */ true, uidUser1, false);
+        mHelper.createNotificationChannel(PKG_P, uidUser1, channelUser1NoBypass, true,
+                /* hasDndAccess= */ true, uidUser1, false);
+        mHelper.createNotificationChannel(PKG_P, uidUser2, channelUser2Bypass, true,
+                /* hasDndAccess= */ true, uidUser2, false);
+
+        assertThat(mHelper.getPackagesBypassingDnd(0)).isEmpty();
+        assertThat(mHelper.getPackagesBypassingDnd(1))
+                .containsExactly(new ZenBypassingApp(PKG_P, false));
+        assertThat(mHelper.getPackagesBypassingDnd(2))
+                .containsExactly(new ZenBypassingApp(PKG_P, true));
+    }
+
+    @Test
     public void getPackagesBypassingDnd_oneChannelBypassing_groupBlocked() {
         int uid = UID_N_MR1;
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
diff --git a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
index 05a1482..33ccec3 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
@@ -18,11 +18,16 @@
 import static android.view.KeyEvent.KEYCODE_POWER;
 import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
 
+import static com.android.hardware.input.Flags.FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT;
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS;
+import static com.android.server.policy.PhoneWindowManager.POWER_MULTI_PRESS_TIMEOUT_MILLIS;
 import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_DREAM_OR_SLEEP;
 import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_POWER_GO_TO_SLEEP;
 
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.EnableFlags;
 import android.provider.Settings;
 import android.view.Display;
 
@@ -39,6 +44,7 @@
     @Before
     public void setUp() {
         setUpPhoneWindowManager();
+        mPhoneWindowManager.overrideStatusBarManagerInternal();
     }
 
     /**
@@ -50,6 +56,8 @@
         sendKey(KEYCODE_POWER);
         mPhoneWindowManager.assertPowerSleep();
 
+        mPhoneWindowManager.moveTimeForward(POWER_MULTI_PRESS_TIMEOUT_MILLIS);
+
         // turn screen on when begin from non-interactive.
         mPhoneWindowManager.overrideDisplayState(Display.STATE_OFF);
         sendKey(KEYCODE_POWER);
@@ -90,7 +98,7 @@
         mPhoneWindowManager.overrideCanStartDreaming(false);
         sendKey(KEYCODE_POWER);
         sendKey(KEYCODE_POWER);
-        mPhoneWindowManager.assertCameraLaunch();
+        mPhoneWindowManager.assertDoublePowerLaunch();
         mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
     }
 
@@ -101,7 +109,7 @@
     public void testPowerDoublePress() {
         sendKey(KEYCODE_POWER);
         sendKey(KEYCODE_POWER);
-        mPhoneWindowManager.assertCameraLaunch();
+        mPhoneWindowManager.assertDoublePowerLaunch();
     }
 
     /**
@@ -111,12 +119,14 @@
     public void testPowerLongPress() {
         // Show assistant.
         mPhoneWindowManager.overrideLongPressOnPower(LONG_PRESS_POWER_ASSISTANT);
-        sendKey(KEYCODE_POWER, true);
+        sendKey(KEYCODE_POWER, SingleKeyGestureDetector.sDefaultLongPressTimeout);
         mPhoneWindowManager.assertSearchManagerLaunchAssist();
 
+        mPhoneWindowManager.moveTimeForward(POWER_MULTI_PRESS_TIMEOUT_MILLIS);
+
         // Show global actions.
         mPhoneWindowManager.overrideLongPressOnPower(LONG_PRESS_POWER_GLOBAL_ACTIONS);
-        sendKey(KEYCODE_POWER, true);
+        sendKey(KEYCODE_POWER, SingleKeyGestureDetector.sDefaultLongPressTimeout);
         mPhoneWindowManager.assertShowGlobalActionsCalled();
     }
 
@@ -141,4 +151,143 @@
         sendKey(KEYCODE_POWER);
         mPhoneWindowManager.assertNoPowerSleep();
     }
+
+
+    /**
+     * Double press of power when the window handles the power key events. The
+     * system double power gesture launch should not be performed.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerDoublePress_windowHasOverridePermissionAndKeysHandled() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+
+        sendKey(KEYCODE_POWER);
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
+
+        mPhoneWindowManager.assertNoDoublePowerLaunch();
+    }
+
+    /**
+     * Double press of power when the window doesn't handle the power key events.
+     * The system default gesture launch should be performed and the app should receive both events.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerDoublePress_windowHasOverridePermissionAndKeysUnHandled() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> false);
+
+        sendKey(KEYCODE_POWER);
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
+        mPhoneWindowManager.assertDoublePowerLaunch();
+        assertEquals(getDownKeysDispatched(), 2);
+        assertEquals(getUpKeysDispatched(), 2);
+    }
+
+    /**
+     * Triple press of power when the window handles the power key double press gesture.
+     * The system default gesture launch should not be performed, and the app only receives the
+     * first two presses.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerTriplePress_windowHasOverridePermissionAndKeysHandled() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+
+        sendKey(KEYCODE_POWER);
+        sendKey(KEYCODE_POWER);
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.assertDidNotLockAfterAppTransitionFinished();
+        mPhoneWindowManager.assertNoDoublePowerLaunch();
+        assertEquals(getDownKeysDispatched(), 2);
+        assertEquals(getUpKeysDispatched(), 2);
+    }
+
+    /**
+     * Tests a single press, followed by a double press when the window can handle the power key.
+     * The app should receive all 3 events.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerTriplePressWithDelay_windowHasOverridePermissionAndKeysHandled() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+
+        sendKey(KEYCODE_POWER);
+        mPhoneWindowManager.moveTimeForward(POWER_MULTI_PRESS_TIMEOUT_MILLIS);
+        sendKey(KEYCODE_POWER);
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.assertNoDoublePowerLaunch();
+        assertEquals(getDownKeysDispatched(), 3);
+        assertEquals(getUpKeysDispatched(), 3);
+    }
+
+    /**
+     * Tests single press when window doesn't handle the power key. Phone should go to sleep.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerSinglePress_windowHasOverridePermissionAndKeyUnhandledByApp() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> false);
+        mPhoneWindowManager.overrideShortPressOnPower(SHORT_PRESS_POWER_GO_TO_SLEEP);
+
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.assertPowerSleep();
+    }
+
+    /**
+     * Tests single press when the window handles the power key. Phone should go to sleep after a
+     * delay of {POWER_MULTI_PRESS_TIMEOUT_MILLIS}
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerSinglePress_windowHasOverridePermissionAndKeyHandledByApp() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+        mPhoneWindowManager.overrideDisplayState(Display.STATE_ON);
+        mPhoneWindowManager.overrideShortPressOnPower(SHORT_PRESS_POWER_GO_TO_SLEEP);
+
+        sendKey(KEYCODE_POWER);
+
+        mPhoneWindowManager.moveTimeForward(POWER_MULTI_PRESS_TIMEOUT_MILLIS);
+
+        mPhoneWindowManager.assertPowerSleep();
+    }
+
+
+    /**
+     * Tests 5x press when the window handles the power key. Emergency gesture should still be
+     * launched.
+     */
+    @Test
+    @EnableFlags(FLAG_OVERRIDE_POWER_KEY_BEHAVIOR_IN_FOCUSED_WINDOW)
+    public void testPowerFiveTimesPress_windowHasOverridePermissionAndKeyHandledByApp() {
+        mPhoneWindowManager.overrideCanWindowOverridePowerKey(true);
+        setDispatchedKeyHandler(keyEvent -> true);
+        mPhoneWindowManager.overrideDisplayState(Display.STATE_ON);
+        mPhoneWindowManager.overrideShortPressOnPower(SHORT_PRESS_POWER_GO_TO_SLEEP);
+
+        int minEmergencyGestureDurationMillis = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis);
+        int durationMillis = minEmergencyGestureDurationMillis / 4;
+        for (int i = 0; i < 5; ++i) {
+            sendKey(KEYCODE_POWER);
+            mPhoneWindowManager.moveTimeForward(durationMillis);
+        }
+
+        mPhoneWindowManager.assertEmergencyLaunch();
+        assertEquals(getDownKeysDispatched(), 2);
+        assertEquals(getUpKeysDispatched(), 2);
+    }
 }
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 9e47a00..8ede9ef 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -85,7 +85,9 @@
     private Resources mResources;
     private PackageManager mPackageManager;
     TestPhoneWindowManager mPhoneWindowManager;
-    DispatchedKeyHandler mDispatchedKeyHandler = event -> false;
+    DispatchedKeyHandler mDispatchedKeyHandler;
+    private int mDownKeysDispatched;
+    private int mUpKeysDispatched;
     Context mContext;
 
     /** Modifier key to meta state */
@@ -116,6 +118,9 @@
         XmlResourceParser testBookmarks = mResources.getXml(
                 com.android.frameworks.wmtests.R.xml.bookmarks);
         doReturn(testBookmarks).when(mResources).getXml(com.android.internal.R.xml.bookmarks);
+        mDispatchedKeyHandler = event -> false;
+        mDownKeysDispatched = 0;
+        mUpKeysDispatched = 0;
 
         try {
             // Keep packageName / className in sync with
@@ -229,6 +234,10 @@
         sendKeyCombination(new int[]{keyCode}, 0 /*durationMillis*/, longPress, DEFAULT_DISPLAY);
     }
 
+    void sendKey(int keyCode, long durationMillis) {
+        sendKeyCombination(new int[]{keyCode}, durationMillis, false, DEFAULT_DISPLAY);
+    }
+
     boolean sendKeyGestureEventStart(int gestureType) {
         return mPhoneWindowManager.sendKeyGestureEvent(
                 new KeyGestureEvent.Builder().setKeyGestureType(gestureType).setAction(
@@ -278,6 +287,14 @@
         doReturn(expectedBehavior).when(mResources).getInteger(eq(resId));
     }
 
+    int getDownKeysDispatched() {
+        return mDownKeysDispatched;
+    }
+
+    int getUpKeysDispatched() {
+        return mUpKeysDispatched;
+    }
+
     private void interceptKey(KeyEvent keyEvent) {
         int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
         if ((actions & ACTION_PASS_TO_USER) != 0) {
@@ -285,6 +302,11 @@
                 if (!mDispatchedKeyHandler.onKeyDispatched(keyEvent)) {
                     mPhoneWindowManager.interceptUnhandledKey(keyEvent);
                 }
+                if (keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
+                    ++mDownKeysDispatched;
+                } else {
+                    ++mUpKeysDispatched;
+                }
             }
         }
         mPhoneWindowManager.dispatchAllPendingEvents();
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 285d94d..6c48ba2 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -37,6 +37,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT;
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS;
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GO_TO_VOICE_ASSIST;
@@ -45,10 +46,14 @@
 import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
 import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.after;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.description;
 import static org.mockito.Mockito.mockingDetails;
 import static org.mockito.Mockito.timeout;
@@ -85,7 +90,9 @@
 import android.os.test.TestLooper;
 import android.provider.Settings;
 import android.service.dreams.DreamManagerInternal;
+import android.service.quickaccesswallet.QuickAccessWalletClient;
 import android.telecom.TelecomManager;
+import android.util.MutableBoolean;
 import android.view.Display;
 import android.view.InputEvent;
 import android.view.KeyCharacterMap;
@@ -95,9 +102,12 @@
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
 import com.android.internal.policy.KeyInterceptionInfo;
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
+import com.android.server.SystemService;
 import com.android.server.input.InputManagerInternal;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.pm.UserManagerInternal;
@@ -120,6 +130,7 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
 
 import java.util.List;
 import java.util.function.Supplier;
@@ -132,6 +143,7 @@
 
     private PhoneWindowManager mPhoneWindowManager;
     private Context mContext;
+    private GestureLauncherService mGestureLauncherService;
 
     @Mock private WindowManagerInternal mWindowManagerInternal;
     @Mock private ActivityManagerInternal mActivityManagerInternal;
@@ -163,7 +175,9 @@
     @Mock private DisplayRotation mDisplayRotation;
     @Mock private DisplayPolicy mDisplayPolicy;
     @Mock private WindowManagerPolicy.ScreenOnListener mScreenOnListener;
-    @Mock private GestureLauncherService mGestureLauncherService;
+    @Mock private QuickAccessWalletClient mQuickAccessWalletClient;
+    @Mock private MetricsLogger mMetricsLogger;
+    @Mock private UiEventLogger mUiEventLogger;
     @Mock private GlobalActions mGlobalActions;
     @Mock private AccessibilityShortcutController mAccessibilityShortcutController;
 
@@ -192,6 +206,8 @@
 
     private int mKeyEventPolicyFlags = FLAG_INTERACTIVE;
 
+    private int mProcessPowerKeyDownCount = 0;
+
     private class TestTalkbackShortcutController extends TalkbackShortcutController {
         TestTalkbackShortcutController(Context context) {
             super(context);
@@ -260,6 +276,8 @@
         MockitoAnnotations.initMocks(this);
         mHandler = new Handler(mTestLooper.getLooper());
         mContext = mockingDetails(context).isSpy() ? context : spy(context);
+        mGestureLauncherService = spy(new GestureLauncherService(mContext, mMetricsLogger,
+                mQuickAccessWalletClient, mUiEventLogger));
         setUp(supportSettingsUpdate);
         mTestLooper.dispatchAll();
     }
@@ -272,6 +290,7 @@
         mMockitoSession = mockitoSession()
                 .mockStatic(LocalServices.class, spyStubOnly)
                 .mockStatic(KeyCharacterMap.class)
+                .mockStatic(GestureLauncherService.class)
                 .strictness(Strictness.LENIENT)
                 .startMocking();
 
@@ -296,6 +315,16 @@
                 () -> LocalServices.getService(eq(DisplayManagerInternal.class)));
         doReturn(mGestureLauncherService).when(
                 () -> LocalServices.getService(eq(GestureLauncherService.class)));
+        doReturn(true).when(
+                () -> GestureLauncherService.isCameraDoubleTapPowerSettingEnabled(any(), anyInt())
+        );
+        doReturn(true).when(
+                () -> GestureLauncherService.isEmergencyGestureSettingEnabled(any(), anyInt())
+        );
+        doReturn(true).when(
+                () -> GestureLauncherService.isGestureLauncherEnabled(any())
+        );
+        mGestureLauncherService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
         doReturn(mUserManagerInternal).when(
                 () -> LocalServices.getService(eq(UserManagerInternal.class)));
         doReturn(null).when(() -> LocalServices.getService(eq(VrManagerInternal.class)));
@@ -375,7 +404,7 @@
         doNothing().when(mContext).startActivityAsUser(any(), any());
         doNothing().when(mContext).startActivityAsUser(any(), any(), any());
 
-        KeyInterceptionInfo interceptionInfo = new KeyInterceptionInfo(0, 0, null, 0);
+        KeyInterceptionInfo interceptionInfo = new KeyInterceptionInfo(0, 0, null, 0, 0);
         doReturn(interceptionInfo)
                 .when(mWindowManagerInternal).getKeyInterceptionInfoFromToken(any());
 
@@ -393,6 +422,8 @@
                 eq(TEST_BROWSER_ROLE_PACKAGE_NAME));
         doReturn(mSmsIntent).when(mPackageManager).getLaunchIntentForPackage(
                 eq(TEST_SMS_ROLE_PACKAGE_NAME));
+        mProcessPowerKeyDownCount = 0;
+        captureProcessPowerKeyDownCount();
 
         Mockito.reset(mContext);
     }
@@ -650,6 +681,12 @@
                 .when(mButtonOverridePermissionChecker).canAppOverrideSystemKey(any(), anyInt());
     }
 
+    void overrideCanWindowOverridePowerKey(boolean granted) {
+        doReturn(granted)
+                .when(mButtonOverridePermissionChecker).canWindowOverridePowerKey(any(), anyInt(),
+                        anyInt());
+    }
+
     void overrideKeyEventPolicyFlags(int flags) {
         mKeyEventPolicyFlags = flags;
     }
@@ -725,11 +762,56 @@
         verify(mPowerManager, never()).goToSleep(anyLong(), anyInt(), anyInt());
     }
 
-    void assertCameraLaunch() {
+    void assertDoublePowerLaunch() {
+        ArgumentCaptor<MutableBoolean> valueCaptor = ArgumentCaptor.forClass(MutableBoolean.class);
+
         mTestLooper.dispatchAll();
-        // GestureLauncherService should receive interceptPowerKeyDown twice.
-        verify(mGestureLauncherService, times(2))
-                .interceptPowerKeyDown(any(), anyBoolean(), any());
+        verify(mGestureLauncherService, atLeast(2))
+                .interceptPowerKeyDown(any(), anyBoolean(), valueCaptor.capture());
+        verify(mGestureLauncherService, atMost(4))
+                .interceptPowerKeyDown(any(), anyBoolean(), valueCaptor.capture());
+
+        if (overridePowerKeyBehaviorInFocusedWindow()) {
+            assertTrue(mProcessPowerKeyDownCount >= 2 && mProcessPowerKeyDownCount <= 4);
+        }
+
+        List<Boolean> capturedValues = valueCaptor.getAllValues().stream()
+                .map(mutableBoolean -> mutableBoolean.value)
+                .toList();
+
+        assertTrue(capturedValues.contains(true));
+    }
+
+    void assertNoDoublePowerLaunch() {
+        ArgumentCaptor<MutableBoolean> valueCaptor = ArgumentCaptor.forClass(MutableBoolean.class);
+
+        mTestLooper.dispatchAll();
+        verify(mGestureLauncherService, atLeast(0))
+                .interceptPowerKeyDown(any(), anyBoolean(), valueCaptor.capture());
+
+        List<Boolean> capturedValues = valueCaptor.getAllValues().stream()
+                .map(mutableBoolean -> mutableBoolean.value)
+                .toList();
+
+        assertTrue(capturedValues.stream().noneMatch(value -> value));
+    }
+
+    void assertEmergencyLaunch() {
+        ArgumentCaptor<MutableBoolean> valueCaptor = ArgumentCaptor.forClass(MutableBoolean.class);
+
+        mTestLooper.dispatchAll();
+        verify(mGestureLauncherService, atLeast(1))
+                .interceptPowerKeyDown(any(), anyBoolean(), valueCaptor.capture());
+
+        if (overridePowerKeyBehaviorInFocusedWindow()) {
+            assertEquals(mProcessPowerKeyDownCount, 5);
+        }
+
+        List<Boolean> capturedValues = valueCaptor.getAllValues().stream()
+                .map(mutableBoolean -> mutableBoolean.value)
+                .toList();
+
+        assertTrue(capturedValues.getLast());
     }
 
     void assertSearchManagerLaunchAssist() {
@@ -952,4 +1034,12 @@
         verify(mContext, never()).startActivityAsUser(any(), any(), any());
         verify(mContext, never()).startActivityAsUser(any(), any());
     }
+
+    private void captureProcessPowerKeyDownCount() {
+        doAnswer((Answer<Void>) invocation -> {
+            invocation.callRealMethod();
+            mProcessPowerKeyDownCount++;
+            return null;
+        }).when(mGestureLauncherService).processPowerKeyDown(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
index a7fc10f..948371f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivitySnapshotControllerTests.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.never;
 
@@ -253,7 +254,11 @@
      */
     @Test
     public void testSkipRecordActivity() {
-        doReturn(createSnapshot()).when(mActivitySnapshotController).recordSnapshotInner(any());
+        final AbsAppSnapshotController.SnapshotSupplier supplier =
+                new AbsAppSnapshotController.SnapshotSupplier();
+        supplier.setSupplier(this::createSnapshot);
+        doReturn(supplier).when(mActivitySnapshotController).recordSnapshotInner(
+                any(), anyBoolean(), any());
         final Task task = createTask(mDisplayContent);
 
         mSnapshotPersistQueue.setPaused(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 670f9f6..bacf5ed 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -53,7 +53,9 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -66,6 +68,7 @@
 import com.android.internal.app.UnlaunchableAppActivity;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService;
+import com.android.window.flags.Flags;
 
 import org.junit.After;
 import org.junit.Before;
@@ -133,6 +136,8 @@
     private SparseArray<ActivityInterceptorCallback> mActivityInterceptorCallbacks =
             new SparseArray<>();
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Before
     public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
@@ -237,6 +242,20 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_NORMALIZE_HOME_INTENT)
+    public void testInterceptIncorrectHomeIntent() {
+        // Create a non-standard home intent
+        final Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+        // Ensure the intent is intercepted and normalized to standard home intent.
+        assertTrue(mInterceptor.intercept(homeIntent, null, mAInfo, null, null, null, 0, 0, null,
+                mTaskDisplayArea, false));
+        assertTrue(ActivityRecord.isHomeIntent(homeIntent));
+    }
+
+    @Test
     public void testInterceptLockTaskModeViolationPackage() {
         when(mLockTaskController.isActivityAllowed(
                 TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java
index 8747cfa..9d191ce 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationOverridesTest.java
@@ -335,8 +335,7 @@
         }
 
         private AppCompatOrientationOverrides getTopOrientationOverrides() {
-            return activity().top().mAppCompatController.getAppCompatOverrides()
-                    .getAppCompatOrientationOverrides();
+            return activity().top().mAppCompatController.getAppCompatOrientationOverrides();
         }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java
index 90bf5f0..a21ab5d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationPolicyTest.java
@@ -601,8 +601,7 @@
         }
 
         private AppCompatOrientationOverrides getTopOrientationOverrides() {
-            return activity().top().mAppCompatController.getAppCompatOverrides()
-                    .getAppCompatOrientationOverrides();
+            return activity().top().mAppCompatController.getAppCompatOrientationOverrides();
         }
 
         private AppCompatOrientationPolicy getTopAppCompatOrientationPolicy() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
index 1edbcd5..463254c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatReachabilityOverridesTest.java
@@ -23,14 +23,10 @@
 
 import android.compat.testing.PlatformCompatChangeRule;
 import android.graphics.Rect;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.annotation.NonNull;
 
-import com.android.window.flags.Flags;
-
 import junit.framework.Assert;
 
 import org.junit.Rule;
@@ -125,8 +121,7 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
-    public void testAllowReachabilityForThinLetterboxWithFlagEnabled() {
+    public void testAllowReachabilityForThinLetterbox_disableForThinLetterboxing() {
         runTestScenario((robot) -> {
             robot.activity().createActivityWithComponent();
 
@@ -142,24 +137,6 @@
         });
     }
 
-    @Test
-    @DisableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
-    public void testAllowReachabilityForThinLetterboxWithFlagDisabled() {
-        runTestScenario((robot) -> {
-            robot.activity().createActivityWithComponent();
-
-            robot.configureIsVerticalThinLetterboxed(/* isThin */ true);
-            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ true);
-            robot.configureIsHorizontalThinLetterboxed(/* isThin */ true);
-            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ true);
-
-            robot.configureIsVerticalThinLetterboxed(/* isThin */ false);
-            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ true);
-            robot.configureIsHorizontalThinLetterboxed(/* isThin */ false);
-            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ true);
-        });
-    }
-
     /**
      * Runs a test scenario providing a Robot.
      */
diff --git a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java
index 748a47a..b6f4424 100644
--- a/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/CameraCompatFreeformPolicyTests.java
@@ -26,6 +26,7 @@
 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -44,6 +45,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -54,6 +56,7 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.annotation.NonNull;
 import android.app.CameraCompatTaskInfo;
 import android.app.IApplicationThread;
 import android.app.WindowConfiguration.WindowingMode;
@@ -109,56 +112,25 @@
     private CameraManager.AvailabilityCallback mCameraAvailabilityCallback;
     private CameraCompatFreeformPolicy mCameraCompatFreeformPolicy;
     private ActivityRecord mActivity;
-    private ActivityRefresher mActivityRefresher;
 
+    // TODO(b/384465100): use a robot structure.
     @Before
     public void setUp() throws Exception {
-        mAppCompatConfiguration = mDisplayContent.mWmService.mAppCompatConfiguration;
-        spyOn(mAppCompatConfiguration);
-        when(mAppCompatConfiguration.isCameraCompatTreatmentEnabled()).thenReturn(true);
-        when(mAppCompatConfiguration.isCameraCompatRefreshEnabled()).thenReturn(true);
-        when(mAppCompatConfiguration.isCameraCompatRefreshCycleThroughStopEnabled())
-                .thenReturn(true);
-
-        final CameraManager mockCameraManager = mock(CameraManager.class);
-        doAnswer(invocation -> {
-            mCameraAvailabilityCallback = invocation.getArgument(1);
-            return null;
-        }).when(mockCameraManager).registerAvailabilityCallback(
-                any(Executor.class), any(CameraManager.AvailabilityCallback.class));
-
-        when(mContext.getSystemService(CameraManager.class)).thenReturn(mockCameraManager);
-
-        mDisplayContent.setIgnoreOrientationRequest(true);
-
-        final Handler mockHandler = mock(Handler.class);
-
-        when(mockHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(
-                invocation -> {
-                    ((Runnable) invocation.getArgument(0)).run();
-                    return null;
-                });
-
-        mActivityRefresher = new ActivityRefresher(mDisplayContent.mWmService, mockHandler);
-        final CameraStateMonitor cameraStateMonitor = new CameraStateMonitor(mDisplayContent,
-                mockHandler);
-        mCameraCompatFreeformPolicy = new CameraCompatFreeformPolicy(mDisplayContent,
-                cameraStateMonitor, mActivityRefresher);
-
-        setDisplayRotation(ROTATION_90);
-        mCameraCompatFreeformPolicy.start();
-        cameraStateMonitor.startListeningToCameraState();
+        setupAppCompatConfiguration();
+        setupCameraManager();
+        setupHandler();
+        doReturn(true).when(() -> DesktopModeHelper.canEnterDesktopMode(any()));
     }
 
     @Test
     @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING)
     @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT})
-    public void testIsCameraRunningAndWindowingModeEligible_featureDisabled_returnsFalse() {
+    public void testFeatureDisabled_cameraCompatFreeformPolicyNotCreated() {
         configureActivity(SCREEN_ORIENTATION_PORTRAIT);
 
         mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
 
-        assertFalse(mCameraCompatFreeformPolicy.isCameraRunningAndWindowingModeEligible(mActivity));
+        assertNull(mCameraCompatFreeformPolicy);
     }
 
     @Test
@@ -203,17 +175,6 @@
     }
 
     @Test
-    @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING)
-    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT})
-    public void testIsFreeformLetterboxingForCameraAllowed_featureDisabled_returnsFalse() {
-        configureActivity(SCREEN_ORIENTATION_PORTRAIT);
-
-        mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
-
-        assertFalse(mCameraCompatFreeformPolicy.isFreeformLetterboxingForCameraAllowed(mActivity));
-    }
-
-    @Test
     @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING)
     public void testIsFreeformLetterboxingForCameraAllowed_overrideDisabled_returnsFalse() {
         configureActivity(SCREEN_ORIENTATION_PORTRAIT);
@@ -341,6 +302,7 @@
         mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
         callOnActivityConfigurationChanging(mActivity, /* letterboxNew= */ true,
                 /* lastLetterbox= */ false);
+        assertActivityRefreshRequested(/* refreshRequested */ true);
         mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1);
         mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
         // Activity is letterboxed from the previous configuration change.
@@ -556,6 +518,40 @@
         assertCompatibilityInfoSentWithDisplayRotation(ROTATION_90);
     }
 
+    private void setupAppCompatConfiguration() {
+        mAppCompatConfiguration = mDisplayContent.mWmService.mAppCompatConfiguration;
+        spyOn(mAppCompatConfiguration);
+        when(mAppCompatConfiguration.isCameraCompatTreatmentEnabled()).thenReturn(true);
+        when(mAppCompatConfiguration.isCameraCompatTreatmentEnabledAtBuildTime()).thenReturn(true);
+        when(mAppCompatConfiguration.isCameraCompatRefreshEnabled()).thenReturn(true);
+        when(mAppCompatConfiguration.isCameraCompatSplitScreenAspectRatioEnabled())
+                .thenReturn(false);
+        when(mAppCompatConfiguration.isCameraCompatRefreshCycleThroughStopEnabled())
+                .thenReturn(true);
+    }
+
+    private void setupCameraManager() {
+        final CameraManager mockCameraManager = mock(CameraManager.class);
+        doAnswer(invocation -> {
+            mCameraAvailabilityCallback = invocation.getArgument(1);
+            return null;
+        }).when(mockCameraManager).registerAvailabilityCallback(
+                any(Executor.class), any(CameraManager.AvailabilityCallback.class));
+
+        when(mContext.getSystemService(CameraManager.class)).thenReturn(mockCameraManager);
+    }
+
+    private void setupHandler() {
+        final Handler handler = mDisplayContent.mWmService.mH;
+        spyOn(handler);
+
+        when(handler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(
+                invocation -> {
+                    ((Runnable) invocation.getArgument(0)).run();
+                    return null;
+                });
+    }
+
     private void configureActivity(@ScreenOrientation int activityOrientation) {
         configureActivity(activityOrientation, WINDOWING_MODE_FREEFORM);
     }
@@ -567,28 +563,57 @@
 
     private void configureActivityAndDisplay(@ScreenOrientation int activityOrientation,
             @Orientation int naturalOrientation, @WindowingMode int windowingMode) {
+        setupDisplayContent(naturalOrientation);
+        final Task task = setupTask(windowingMode);
+        setupActivity(task, activityOrientation, windowingMode);
+        setupMockApplicationThread();
+
+        mCameraCompatFreeformPolicy = mDisplayContent.mAppCompatCameraPolicy
+                .mCameraCompatFreeformPolicy;
+    }
+
+    private void setupDisplayContent(@Orientation int naturalOrientation) {
+        // Create a new DisplayContent so that the flag values create the camera freeform policy.
+        mDisplayContent = new TestDisplayContent.Builder(mAtm, mDisplayContent.getSurfaceWidth(),
+                mDisplayContent.getSurfaceHeight()).build();
+        mDisplayContent.setIgnoreOrientationRequest(true);
+        setDisplayRotation(ROTATION_90);
+        doReturn(naturalOrientation).when(mDisplayContent).getNaturalOrientation();
+    }
+
+    private Task setupTask(@WindowingMode int windowingMode) {
+        final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea();
+        spyOn(tda);
+        doReturn(true).when(tda).supportsNonResizableMultiWindow();
+
         final Task task = new TaskBuilder(mSupervisor)
                 .setDisplay(mDisplayContent)
                 .setWindowingMode(windowingMode)
                 .build();
+        task.setBounds(0, 0, 1000, 500);
+        return task;
+    }
 
+    private void setupActivity(@NonNull Task task, @ScreenOrientation int activityOrientation,
+            @WindowingMode int windowingMode) {
         mActivity = new ActivityBuilder(mAtm)
                 // Set the component to be that of the test class in order to enable compat changes
                 .setComponent(ComponentName.createRelative(mContext,
                         com.android.server.wm.CameraCompatFreeformPolicyTests.class.getName()))
                 .setScreenOrientation(activityOrientation)
+                .setResizeMode(RESIZE_MODE_RESIZEABLE)
+                .setCreateTask(true)
+                .setOnTop(true)
                 .setTask(task)
                 .build();
+        mActivity.mAppCompatController.getAppCompatSizeCompatModePolicy().clearSizeCompatMode();
 
         spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides());
         spyOn(mActivity.info);
 
         doReturn(mActivity).when(mDisplayContent).topRunningActivity(anyBoolean());
-        doReturn(naturalOrientation).when(mDisplayContent).getNaturalOrientation();
-
         doReturn(windowingMode == WINDOWING_MODE_FREEFORM).when(mActivity)
                 .inFreeformWindowingMode();
-        setupMockApplicationThread();
     }
 
     private void assertInCameraCompatMode(@CameraCompatTaskInfo.FreeformCameraCompatMode int mode) {
@@ -625,7 +650,8 @@
 
     private void callOnActivityConfigurationChanging(ActivityRecord activity, boolean letterboxNew,
             boolean lastLetterbox) {
-        mActivityRefresher.onActivityConfigurationChanging(activity,
+        mDisplayContent.mAppCompatCameraPolicy.mActivityRefresher
+                .onActivityConfigurationChanging(activity,
                 /* newConfig */ createConfiguration(letterboxNew),
                 /* lastReportedConfig */ createConfiguration(lastLetterbox));
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index 0a7df5a..0af41ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -450,7 +450,7 @@
     public void testGetOrientation() {
         final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test");
         mDisplayContent.addChild(area, POSITION_TOP);
-        final WindowState win = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay");
+        final WindowState win = newWindowBuilder("overlay", TYPE_APPLICATION_OVERLAY).build();
         win.mAttrs.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
         win.mToken.reparent(area, POSITION_TOP);
         spyOn(win);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index db71f2b..57aacd3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -178,8 +178,8 @@
     @SetupWindows(addAllCommonWindows = true)
     @Test
     public void testForAllWindows() {
-        final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
-                mDisplayContent, "exiting app");
+        final WindowState exitingAppWindow = newWindowBuilder("exiting app",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
         final ActivityRecord exitingApp = exitingAppWindow.mActivityRecord;
         exitingApp.startAnimation(exitingApp.getPendingTransaction(), mock(AnimationAdapter.class),
                 false /* hidden */, SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION);
@@ -211,8 +211,8 @@
     @SetupWindows(addAllCommonWindows = true)
     @Test
     public void testForAllWindows_WithAppImeTarget() {
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
 
         mDisplayContent.setImeLayeringTarget(imeAppTarget);
 
@@ -289,8 +289,8 @@
     public void testForAllWindows_WithInBetweenWindowToken() {
         // This window is set-up to be z-ordered between some windows that go in the same token like
         // the nav bar and status bar.
-        final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
-                mDisplayContent, "voiceInteractionWindow");
+        final WindowState voiceInteractionWindow = newWindowBuilder("voiceInteractionWindow",
+                TYPE_VOICE_INTERACTION).setDisplay(mDisplayContent).build();
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -310,7 +310,8 @@
     @Test
     public void testComputeImeTarget() {
         // Verify that an app window can be an ime target.
-        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+        final WindowState appWin = newWindowBuilder("appWin", TYPE_APPLICATION).setDisplay(
+                mDisplayContent).build();
         appWin.setHasSurface(true);
         assertTrue(appWin.canBeImeTarget());
         WindowState imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
@@ -318,8 +319,8 @@
         appWin.mHidden = false;
 
         // Verify that an child window can be an ime target.
-        final WindowState childWin = createWindow(appWin,
-                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
+        final WindowState childWin = newWindowBuilder("childWin",
+                TYPE_APPLICATION_ATTACHED_DIALOG).setParent(appWin).build();
         childWin.setHasSurface(true);
         assertTrue(childWin.canBeImeTarget());
         imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
@@ -331,8 +332,8 @@
     public void testComputeImeTarget_startingWindow() {
         ActivityRecord activity = createActivityRecord(mDisplayContent);
 
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
-                "startingWin");
+        final WindowState startingWin = newWindowBuilder("startingWin",
+                TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
         startingWin.setHasSurface(true);
         assertTrue(startingWin.canBeImeTarget());
 
@@ -342,7 +343,8 @@
 
         // Verify that the starting window still be an ime target even an app window launching
         // behind it.
-        final WindowState appWin = createWindow(null, TYPE_BASE_APPLICATION, activity, "appWin");
+        final WindowState appWin = newWindowBuilder("appWin", TYPE_BASE_APPLICATION).setWindowToken(
+                activity).build();
         appWin.setHasSurface(true);
         assertTrue(appWin.canBeImeTarget());
 
@@ -352,8 +354,8 @@
 
         // Verify that the starting window still be an ime target even the child window behind a
         // launching app window
-        final WindowState childWin = createWindow(appWin,
-                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
+        final WindowState childWin = newWindowBuilder("childWin",
+                TYPE_APPLICATION_ATTACHED_DIALOG).setParent(appWin).build();
         childWin.setHasSurface(true);
         assertTrue(childWin.canBeImeTarget());
         imeTarget = mDisplayContent.computeImeTarget(false /* updateImeTarget */);
@@ -365,8 +367,8 @@
         final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
         final ActivityRecord activity = createActivityRecord(mDisplayContent);
 
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
-                "startingWin");
+        final WindowState startingWin = newWindowBuilder("startingWin",
+                TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
         startingWin.setHasSurface(true);
         assertTrue(startingWin.canBeImeTarget());
         final WindowContainer imeSurfaceParentWindow = mock(WindowContainer.class);
@@ -385,10 +387,10 @@
 
     @Test
     public void testComputeImeTargetReturnsNull_windowDidntRequestIme() {
-        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION,
-                new ActivityBuilder(mAtm).setCreateTask(true).build(), "app");
-        final WindowState win2 = createWindow(null, TYPE_BASE_APPLICATION,
-                new ActivityBuilder(mAtm).setCreateTask(true).build(), "app2");
+        final WindowState win1 = newWindowBuilder("app", TYPE_BASE_APPLICATION).setWindowToken(
+                new ActivityBuilder(mAtm).setCreateTask(true).build()).build();
+        final WindowState win2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).setWindowToken(
+                new ActivityBuilder(mAtm).setCreateTask(true).build()).build();
 
         mDisplayContent.setImeInputTarget(win1);
         mDisplayContent.setImeLayeringTarget(win2);
@@ -404,8 +406,8 @@
         final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
         final ActivityRecord activity = createActivityRecord(mDisplayContent);
 
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
-                "startingWin");
+        final WindowState startingWin = newWindowBuilder("startingWin",
+                TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
         startingWin.setHasSurface(true);
         assertTrue(startingWin.canBeImeTarget());
         final WindowContainer imeSurfaceParentWindow = mock(WindowContainer.class);
@@ -433,8 +435,8 @@
         final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
         final ActivityRecord activity = createActivityRecord(mDisplayContent);
 
-        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
-                "startingWin");
+        final WindowState startingWin = newWindowBuilder("startingWin",
+                TYPE_APPLICATION_STARTING).setWindowToken(activity).build();
         startingWin.setHasSurface(true);
         assertTrue(startingWin.canBeImeTarget());
 
@@ -532,8 +534,8 @@
         mWm.mPerDisplayFocusEnabled = perDisplayFocusEnabled;
 
         // Create a focusable window and check that focus is calculated correctly
-        final WindowState window1 =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
+        final WindowState window1 = newWindowBuilder("window1", TYPE_BASE_APPLICATION).setDisplay(
+                mDisplayContent).build();
         window1.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window1.isFocused());
@@ -549,7 +551,8 @@
         final ActivityRecord app2 = new ActivityBuilder(mAtm)
                 .setTask(new TaskBuilder(mSupervisor).setDisplay(dc).build())
                 .setUseProcess(window1.getProcess()).setOnTop(true).build();
-        final WindowState window2 = createWindow(null, TYPE_BASE_APPLICATION, app2, "window2");
+        final WindowState window2 = newWindowBuilder("window2",
+                TYPE_BASE_APPLICATION).setWindowToken(app2).build();
         window2.mActivityRecord.mTargetSdk = targetSdk;
         updateFocusedWindow();
         assertTrue(window2.isFocused());
@@ -616,7 +619,7 @@
 
     @Test
     public void testDisplayHasContent() {
-        final WindowState window = createWindow(null, TYPE_APPLICATION_OVERLAY, "window");
+        final WindowState window = newWindowBuilder("window", TYPE_APPLICATION_OVERLAY).build();
         setDrawnState(WindowStateAnimator.COMMIT_DRAW_PENDING, window);
         assertFalse(mDisplayContent.getLastHasContent());
         // The pending draw state should be committed and the has-content state is also updated.
@@ -632,7 +635,8 @@
     @Test
     public void testImeIsAttachedToDisplayForLetterboxedApp() {
         final DisplayContent dc = mDisplayContent;
-        final WindowState ws = createWindow(null, TYPE_APPLICATION, dc, "app window");
+        final WindowState ws = newWindowBuilder("app window", TYPE_APPLICATION).setDisplay(
+                dc).build();
         dc.setImeLayeringTarget(ws);
         dc.setImeInputTarget(ws);
 
@@ -655,7 +659,8 @@
         final WindowState[] windows = new WindowState[types.length];
         for (int i = 0; i < types.length; i++) {
             final int type = types[i];
-            windows[i] = createWindow(null /* parent */, type, displayContent, "window-" + type);
+            windows[i] = newWindowBuilder("window-" + type, type).setDisplay(
+                    displayContent).build();
             windows[i].setHasSurface(true);
             windows[i].mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
         }
@@ -887,7 +892,7 @@
     @Test
     public void testLayoutSeq_assignedDuringLayout() {
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+        final WindowState win = newWindowBuilder("w", TYPE_BASE_APPLICATION).setDisplay(dc).build();
 
         performLayout(dc);
 
@@ -902,10 +907,12 @@
 
         // Create a window that requests landscape orientation. It will define device orientation
         // by default.
-        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+        final WindowState window = newWindowBuilder("w", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         window.mActivityRecord.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
-        final WindowState keyguard = createWindow(null, TYPE_NOTIFICATION_SHADE , dc, "keyguard");
+        final WindowState keyguard = newWindowBuilder("keyguard",
+                TYPE_NOTIFICATION_SHADE).setDisplay(dc).build();
         keyguard.mHasSurface = true;
         keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
 
@@ -936,8 +943,8 @@
 
         // Create a window that requests a fixed orientation. It will define device orientation
         // by default.
-        final WindowState window = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY, dc,
-                "window");
+        final WindowState window = newWindowBuilder("window", TYPE_APPLICATION_OVERLAY).setDisplay(
+                dc).build();
         window.mHasSurface = true;
         window.mAttrs.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
 
@@ -1003,12 +1010,14 @@
     public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
         final DisplayContent newDisplay = createNewDisplay();
 
-        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+        final WindowState appWin = newWindowBuilder("appWin", TYPE_APPLICATION).setDisplay(
+                mDisplayContent).build();
         final Task rootTask = mDisplayContent.getTopRootTask();
         final ActivityRecord activity = rootTask.topRunningActivity();
         doReturn(true).when(activity).shouldBeVisibleUnchecked();
 
-        final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
+        final WindowState appWin1 = newWindowBuilder("appWin1", TYPE_APPLICATION).setDisplay(
+                newDisplay).build();
         final Task rootTask1 = newDisplay.getTopRootTask();
         final ActivityRecord activity1 = rootTask1.topRunningActivity();
         doReturn(true).when(activity1).shouldBeVisibleUnchecked();
@@ -1203,7 +1212,7 @@
     @Test
     public void testComputeImeParent_app() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.setImeLayeringTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+        dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build());
         dc.setImeInputTarget(dc.getImeTarget(IME_TARGET_LAYERING).getWindow());
         assertEquals(dc.getImeTarget(
                         IME_TARGET_LAYERING).getWindow().mActivityRecord.getSurfaceControl(),
@@ -1213,7 +1222,7 @@
     @Test
     public void testComputeImeParent_app_notFullscreen() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "app"));
+        dc.setImeLayeringTarget(newWindowBuilder("app", TYPE_STATUS_BAR).build());
         dc.getImeTarget(IME_TARGET_LAYERING).getWindow().setWindowingMode(
                 WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
         dc.setImeInputTarget(dc.getImeTarget(IME_TARGET_LAYERING).getWindow());
@@ -1235,7 +1244,7 @@
     @Test
     public void testComputeImeParent_noApp() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "statusBar"));
+        dc.setImeLayeringTarget(newWindowBuilder("statusBar", TYPE_STATUS_BAR).build());
         dc.setImeInputTarget(dc.getImeTarget(IME_TARGET_LAYERING).getWindow());
         assertEquals(dc.getImeContainer().getParentSurfaceControl(),
                 dc.computeImeParent().getSurfaceControl());
@@ -1244,8 +1253,8 @@
     @SetupWindows(addWindows = W_ACTIVITY)
     @Test
     public void testComputeImeParent_inputTargetNotUpdate() throws Exception {
-        WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1");
-        WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2");
+        WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build();
+        WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build();
         doReturn(true).when(mDisplayContent).shouldImeAttachedToApp();
         mDisplayContent.setImeLayeringTarget(app1);
         mDisplayContent.setImeInputTarget(app1);
@@ -1260,10 +1269,10 @@
     @SetupWindows(addWindows = W_ACTIVITY)
     @Test
     public void testComputeImeParent_updateParentWhenTargetNotUseIme() throws Exception {
-        WindowState overlay = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay");
+        WindowState overlay = newWindowBuilder("overlay", TYPE_APPLICATION_OVERLAY).build();
         overlay.setBounds(100, 100, 200, 200);
         overlay.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM;
-        WindowState app = createWindow(null, TYPE_BASE_APPLICATION, "app");
+        WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).build();
         mDisplayContent.setImeLayeringTarget(overlay);
         mDisplayContent.setImeInputTarget(app);
         assertFalse(mDisplayContent.shouldImeAttachedToApp());
@@ -1274,8 +1283,8 @@
     @Test
     public void testComputeImeParent_remoteControlTarget() throws Exception {
         final DisplayContent dc = mDisplayContent;
-        WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1");
-        WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2");
+        WindowState app1 = newWindowBuilder("app1", TYPE_BASE_APPLICATION).build();
+        WindowState app2 = newWindowBuilder("app2", TYPE_BASE_APPLICATION).build();
 
         dc.setImeLayeringTarget(app1);
         dc.setImeInputTarget(app2);
@@ -1301,7 +1310,7 @@
     public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception {
         final DisplayContent dc = createNewDisplay();
 
-        WindowState app = createWindow(null, TYPE_BASE_APPLICATION, dc, "app");
+        WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).setDisplay(dc).build();
 
         dc.setImeInputTarget(app);
         assertEquals(app, dc.computeImeControlTarget());
@@ -1316,7 +1325,7 @@
     public void testComputeImeControlTarget() throws Exception {
         final DisplayContent dc = createNewDisplay();
         dc.setRemoteInsetsController(createDisplayWindowInsetsController());
-        dc.mCurrentFocus = createWindow(null, TYPE_BASE_APPLICATION, "app");
+        dc.mCurrentFocus = newWindowBuilder("app", TYPE_BASE_APPLICATION).build();
 
         // Expect returning null IME control target when the focus window has not yet been the
         // IME input target (e.g. IME is restarting) in fullscreen windowing mode.
@@ -1332,7 +1341,7 @@
     @Test
     public void testComputeImeControlTarget_splitscreen() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app"));
+        dc.setImeInputTarget(newWindowBuilder("app", TYPE_BASE_APPLICATION).build());
         dc.getImeInputTarget().getWindowState().setWindowingMode(
                 WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
         dc.setImeLayeringTarget(dc.getImeInputTarget().getWindowState());
@@ -1346,7 +1355,7 @@
     public void testImeSecureFlagGetUpdatedAfterImeInputTarget() {
         // Verify IME window can get up-to-date secure flag update when the IME input target
         // set before setCanScreenshot called.
-        final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+        final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build();
         SurfaceControl.Transaction t = mDisplayContent.mInputMethodWindow.getPendingTransaction();
         spyOn(t);
         mDisplayContent.setImeInputTarget(app);
@@ -1391,7 +1400,8 @@
     @Test
     public void testUpdateSystemGestureExclusion() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
 
@@ -1423,11 +1433,12 @@
     @Test
     public void testCalculateSystemGestureExclusion() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win.setSystemGestureExclusion(Collections.singletonList(new Rect(10, 20, 30, 40)));
 
-        final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "win2");
+        final WindowState win2 = newWindowBuilder("win2", TYPE_APPLICATION).setDisplay(dc).build();
         win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win2.setSystemGestureExclusion(Collections.singletonList(new Rect(20, 30, 40, 50)));
 
@@ -1451,11 +1462,12 @@
     @Test
     public void testCalculateSystemGestureExclusion_modal() throws Exception {
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "base");
+        final WindowState win = newWindowBuilder("base", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win.setSystemGestureExclusion(Collections.singletonList(new Rect(0, 0, 1000, 1000)));
 
-        final WindowState win2 = createWindow(null, TYPE_APPLICATION, dc, "modal");
+        final WindowState win2 = newWindowBuilder("modal", TYPE_APPLICATION).setDisplay(dc).build();
         win2.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win2.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
         win2.getAttrs().width = 10;
@@ -1476,7 +1488,8 @@
         mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
 
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
         win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION;
@@ -1500,7 +1513,8 @@
         mWm.mConstants.mSystemGestureExcludedByPreQStickyImmersive = true;
 
         final DisplayContent dc = createNewDisplay();
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, dc, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setDisplay(
+                dc).build();
         win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
         win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         win.getAttrs().privateFlags |= PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION;
@@ -1559,9 +1573,9 @@
     @Test
     public void testHybridRotationAnimation() {
         final DisplayContent displayContent = mDefaultDisplay;
-        final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
-        final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
-        final WindowState app = createWindow(null, TYPE_BASE_APPLICATION, "app");
+        final WindowState statusBar = newWindowBuilder("statusBar", TYPE_STATUS_BAR).build();
+        final WindowState navBar = newWindowBuilder("navBar", TYPE_NAVIGATION_BAR).build();
+        final WindowState app = newWindowBuilder("app", TYPE_BASE_APPLICATION).build();
         final WindowState[] windows = { statusBar, navBar, app };
         makeWindowVisible(windows);
         final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
@@ -1863,6 +1877,11 @@
         assertEquals("Display must be portrait after closing the translucent activity",
                 Configuration.ORIENTATION_PORTRAIT,
                 mDisplayContent.getConfiguration().orientation);
+
+        mDisplayContent.setFixedRotationLaunchingAppUnchecked(nonTopVisible);
+        mDisplayContent.onTransitionFinished();
+        assertFalse("Complete fixed rotation if not in a transition",
+                mDisplayContent.hasTopFixedRotationLaunchingApp());
     }
 
     @Test
@@ -2183,7 +2202,8 @@
         Task rootTask = createTask(display);
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         WindowState activityWindow = createAppWindow(task, TYPE_APPLICATION, "App Window");
-        WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
+        WindowState behindWindow = newWindowBuilder("Screenshot", TYPE_SCREENSHOT).setDisplay(
+                display).build();
 
         WindowState result = display.findScrollCaptureTargetWindow(behindWindow,
                 ActivityTaskManager.INVALID_TASK_ID);
@@ -2196,7 +2216,7 @@
         Task rootTask = createTask(display);
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         WindowState activityWindow = createAppWindow(task, TYPE_APPLICATION, "App Window");
-        WindowState invisible = createWindow(null, TYPE_APPLICATION, "invisible");
+        WindowState invisible = newWindowBuilder("invisible", TYPE_APPLICATION).build();
         invisible.mViewVisibility = View.INVISIBLE;  // make canReceiveKeys return false
 
         WindowState result = display.findScrollCaptureTargetWindow(null,
@@ -2209,7 +2229,7 @@
         DisplayContent display = createNewDisplay();
         Task rootTask = createTask(display);
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
-        WindowState secureWindow = createWindow(null, TYPE_APPLICATION, "Secure Window");
+        WindowState secureWindow = newWindowBuilder("Secure Window", TYPE_APPLICATION).build();
         secureWindow.mAttrs.flags |= FLAG_SECURE;
 
         WindowState result = display.findScrollCaptureTargetWindow(null,
@@ -2222,7 +2242,7 @@
         DisplayContent display = createNewDisplay();
         Task rootTask = createTask(display);
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
-        WindowState secureWindow = createWindow(null, TYPE_APPLICATION, "Secure Window");
+        WindowState secureWindow = newWindowBuilder("Secure window", TYPE_APPLICATION).build();
         secureWindow.mAttrs.flags |= FLAG_SECURE;
 
         WindowState result = display.findScrollCaptureTargetWindow(null,  task.mTaskId);
@@ -2235,7 +2255,8 @@
         Task rootTask = createTask(display);
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         WindowState window = createAppWindow(task, TYPE_APPLICATION, "App Window");
-        WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
+        WindowState behindWindow = newWindowBuilder("Screenshot", TYPE_SCREENSHOT).setDisplay(
+                display).build();
 
         WindowState result = display.findScrollCaptureTargetWindow(null, task.mTaskId);
         assertEquals(window, result);
@@ -2248,7 +2269,8 @@
         Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         WindowState window = createAppWindow(task, TYPE_APPLICATION, "App Window");
         window.mViewVisibility = View.INVISIBLE;  // make canReceiveKeys return false
-        WindowState behindWindow = createWindow(null, TYPE_SCREENSHOT, display, "Screenshot");
+        WindowState behindWindow = newWindowBuilder("Screenshot", TYPE_SCREENSHOT).setDisplay(
+                display).build();
 
         WindowState result = display.findScrollCaptureTargetWindow(null, task.mTaskId);
         assertEquals(window, result);
@@ -2317,9 +2339,10 @@
     @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD })
     @Test
     public void testComputeImeTarget_shouldNotCheckOutdatedImeTargetLayerWhenRemoved() {
-        final WindowState child1 = createWindow(mAppWindow, FIRST_SUB_WINDOW, "child1");
-        final WindowState nextImeTargetApp = createWindow(null /* parent */,
-                TYPE_BASE_APPLICATION, "nextImeTargetApp");
+        final WindowState child1 = newWindowBuilder("child1", FIRST_SUB_WINDOW).setParent(
+                mAppWindow).build();
+        final WindowState nextImeTargetApp = newWindowBuilder("nextImeTargetApp",
+                TYPE_BASE_APPLICATION).build();
         spyOn(child1);
         doReturn(false).when(mDisplayContent).shouldImeAttachedToApp();
         mDisplayContent.setImeLayeringTarget(child1);
@@ -2353,7 +2376,8 @@
 
         // Preparation: Simulate snapshot Task.
         ActivityRecord act1 = createActivityRecord(mDisplayContent);
-        final WindowState appWin1 = createWindow(null, TYPE_BASE_APPLICATION, act1, "appWin1");
+        final WindowState appWin1 = newWindowBuilder("appWin1",
+                TYPE_BASE_APPLICATION).setWindowToken(act1).build();
         spyOn(appWin1);
         spyOn(appWin1.mWinAnimator);
         appWin1.setHasSurface(true);
@@ -2372,7 +2396,8 @@
 
         // Test step 2: Simulate launching appWin2 and appWin1 is in app transition.
         ActivityRecord act2 = createActivityRecord(mDisplayContent);
-        final WindowState appWin2 = createWindow(null, TYPE_BASE_APPLICATION, act2, "appWin2");
+        final WindowState appWin2 = newWindowBuilder("appWin2",
+                TYPE_BASE_APPLICATION).setWindowToken(act2).build();
         appWin2.setHasSurface(true);
         assertTrue(appWin2.canBeImeTarget());
         doReturn(true).when(appWin1).inTransitionSelfOrParent();
@@ -2394,7 +2419,8 @@
         final Task rootTask = createTask(mDisplayContent);
         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+                activity).build();
         task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
         doReturn(true).when(task).okToAnimate();
         ArrayList<WindowContainer> sources = new ArrayList<>();
@@ -2420,7 +2446,8 @@
         final Task rootTask = createTask(mDisplayContent);
         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+                activity).build();
 
         mDisplayContent.setImeLayeringTarget(win);
         mDisplayContent.setImeInputTarget(win);
@@ -2446,7 +2473,8 @@
         final Task rootTask = createTask(mDisplayContent);
         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+                activity).build();
         win.onSurfaceShownChanged(true);
         makeWindowVisible(win, mDisplayContent.mInputMethodWindow);
         task.getDisplayContent().prepareAppTransition(TRANSIT_CLOSE);
@@ -2471,7 +2499,8 @@
         final Task rootTask = createTask(mDisplayContent);
         final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
         final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+        final WindowState win = newWindowBuilder("win", TYPE_BASE_APPLICATION).setWindowToken(
+                activity).build();
         makeWindowVisible(mDisplayContent.mInputMethodWindow);
 
         mDisplayContent.setImeLayeringTarget(win);
@@ -2687,7 +2716,8 @@
     public void testKeyguardGoingAwayWhileAodShown() {
         mDisplayContent.getDisplayPolicy().setAwake(true);
 
-        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+        final WindowState appWin = newWindowBuilder("appWin", TYPE_APPLICATION).setDisplay(
+                mDisplayContent).build();
         final ActivityRecord activity = appWin.mActivityRecord;
 
         mAtm.mKeyguardController.setKeyguardShown(appWin.getDisplayId(), true /* keyguardShowing */,
@@ -2713,15 +2743,15 @@
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testImeChildWindowFocusWhenImeLayeringTargetChanges() {
-        final WindowState imeChildWindow =
-                createWindow(mImeWindow, TYPE_APPLICATION_ATTACHED_DIALOG, "imeChildWindow");
+        final WindowState imeChildWindow = newWindowBuilder("imeChildWindow",
+                TYPE_APPLICATION_ATTACHED_DIALOG).setParent(mImeWindow).build();
         makeWindowVisibleAndDrawn(imeChildWindow, mImeWindow);
         assertTrue(imeChildWindow.canReceiveKeys());
         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
 
         // Verify imeChildWindow can be focused window if the next IME target requests IME visible.
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
         mDisplayContent.setImeLayeringTarget(imeAppTarget);
         spyOn(imeAppTarget);
         doReturn(true).when(imeAppTarget).isRequestedVisible(ime());
@@ -2729,8 +2759,8 @@
 
         // Verify imeChildWindow doesn't be focused window if the next IME target does not
         // request IME visible.
-        final WindowState nextImeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "nextImeAppTarget");
+        final WindowState nextImeAppTarget = newWindowBuilder("nextImeAppTarget",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
         mDisplayContent.setImeLayeringTarget(nextImeAppTarget);
         assertNotEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
     }
@@ -2738,22 +2768,22 @@
     @SetupWindows(addWindows = W_INPUT_METHOD)
     @Test
     public void testImeMenuDialogFocusWhenImeLayeringTargetChanges() {
-        final WindowState imeMenuDialog =
-                createWindow(null, TYPE_INPUT_METHOD_DIALOG, "imeMenuDialog");
+        final WindowState imeMenuDialog = newWindowBuilder("imeMenuDialog",
+                TYPE_INPUT_METHOD_DIALOG).build();
         makeWindowVisibleAndDrawn(imeMenuDialog, mImeWindow);
         assertTrue(imeMenuDialog.canReceiveKeys());
         mDisplayContent.setInputMethodWindowLocked(mImeWindow);
 
         // Verify imeMenuDialog can be focused window if the next IME target requests IME visible.
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = newWindowBuilder("imeAppTarget",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
         mDisplayContent.setImeLayeringTarget(imeAppTarget);
         imeAppTarget.setRequestedVisibleTypes(ime());
         assertEquals(imeMenuDialog, mDisplayContent.findFocusedWindow());
 
         // Verify imeMenuDialog doesn't be focused window if the next IME target is closing.
-        final WindowState nextImeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "nextImeAppTarget");
+        final WindowState nextImeAppTarget = newWindowBuilder("nextImeAppTarget",
+                TYPE_BASE_APPLICATION).setDisplay(mDisplayContent).build();
         makeWindowVisibleAndDrawn(nextImeAppTarget);
         // Even if the app still requests IME, the ime dialog should not gain focus if the target
         // app is invisible.
@@ -2765,10 +2795,12 @@
 
     @Test
     public void testKeepClearAreasMultipleWindows() {
-        final WindowState w1 = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent, "w1");
+        final WindowState w1 = newWindowBuilder("w1", TYPE_NAVIGATION_BAR).setDisplay(
+                mDisplayContent).build();
         final Rect rect1 = new Rect(0, 0, 10, 10);
         w1.setKeepClearAreas(Arrays.asList(rect1), Collections.emptyList());
-        final WindowState w2 = createWindow(null, TYPE_NOTIFICATION_SHADE, mDisplayContent, "w2");
+        final WindowState w2 = newWindowBuilder("w2", TYPE_NOTIFICATION_SHADE).setDisplay(
+                mDisplayContent).build();
         final Rect rect2 = new Rect(10, 10, 20, 20);
         w2.setKeepClearAreas(Arrays.asList(rect2), Collections.emptyList());
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 1015651..ceb0649 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -76,7 +76,7 @@
 
     @Before
     public void setUp() throws Exception {
-        mWindow = spy(createWindow(null, TYPE_APPLICATION, "window"));
+        mWindow = spy(newWindowBuilder("window", TYPE_APPLICATION).build());
 
         spyOn(mStatusBarWindow);
         spyOn(mNavBarWindow);
@@ -147,7 +147,7 @@
     public void addingWindow_withInsetsTypes() {
         mDisplayPolicy.removeWindowLw(mStatusBarWindow);  // Removes the existing one.
 
-        final WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "statusBar");
+        final WindowState win = newWindowBuilder("statusBar", TYPE_STATUS_BAR_SUB_PANEL).build();
         final Binder owner = new Binder();
         win.mAttrs.providedInsets = new InsetsFrameProvider[] {
                 new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars()),
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 27d46fc..ea925c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -76,7 +76,7 @@
 public class DisplayPolicyTests extends WindowTestsBase {
 
     private WindowState createOpaqueFullscreen(boolean hasLightNavBar) {
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "opaqueFullscreen");
+        final WindowState win = newWindowBuilder("opaqueFullscreen", TYPE_BASE_APPLICATION).build();
         final WindowManager.LayoutParams attrs = win.mAttrs;
         attrs.width = MATCH_PARENT;
         attrs.height = MATCH_PARENT;
@@ -99,7 +99,7 @@
     }
 
     private WindowState createDimmingDialogWindow(boolean canBeImTarget) {
-        final WindowState win = spy(createWindow(null, TYPE_APPLICATION, "dimmingDialog"));
+        final WindowState win = spy(newWindowBuilder("dimmingDialog", TYPE_APPLICATION).build());
         final WindowManager.LayoutParams attrs = win.mAttrs;
         attrs.width = WRAP_CONTENT;
         attrs.height = WRAP_CONTENT;
@@ -111,7 +111,7 @@
 
     private WindowState createInputMethodWindow(boolean visible, boolean drawNavBar,
             boolean hasLightNavBar) {
-        final WindowState win = createWindow(null, TYPE_INPUT_METHOD, "inputMethod");
+        final WindowState win = newWindowBuilder("inputMethod", TYPE_INPUT_METHOD).build();
         final WindowManager.LayoutParams attrs = win.mAttrs;
         attrs.width = MATCH_PARENT;
         attrs.height = MATCH_PARENT;
@@ -301,7 +301,7 @@
     }
 
     private WindowState createApplicationWindow() {
-        final WindowState win = createWindow(null, TYPE_APPLICATION, "Application");
+        final WindowState win = newWindowBuilder("Application", TYPE_APPLICATION).build();
         final WindowManager.LayoutParams attrs = win.mAttrs;
         attrs.width = MATCH_PARENT;
         attrs.height = MATCH_PARENT;
@@ -312,7 +312,7 @@
     }
 
     private WindowState createBaseApplicationWindow() {
-        final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "Application");
+        final WindowState win = newWindowBuilder("Application", TYPE_BASE_APPLICATION).build();
         final WindowManager.LayoutParams attrs = win.mAttrs;
         attrs.width = MATCH_PARENT;
         attrs.height = MATCH_PARENT;
@@ -450,7 +450,7 @@
         displayPolicy.getDecorInsetsInfo(Surface.ROTATION_90, di.logicalHeight, di.logicalWidth);
         // Add a window that provides the same insets in current rotation. But it specifies
         // different insets in other rotations.
-        final WindowState bar2 = createWindow(null, navbar.mAttrs.type, "bar2");
+        final WindowState bar2 = newWindowBuilder("bar2", navbar.mAttrs.type).build();
         bar2.mAttrs.providedInsets = new InsetsFrameProvider[] {
                 new InsetsFrameProvider(bar2, 0, WindowInsets.Type.navigationBars())
                         .setInsetsSize(Insets.of(0, 0, 0, NAV_BAR_HEIGHT))
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index ffe3893..b1cad51 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -516,6 +516,12 @@
         // Verify that newly created displays are created with correct rotation settings
         assertFalse(dcDontIgnoreOrientation.getIgnoreOrientationRequest());
         assertTrue(dcIgnoreOrientation.getIgnoreOrientationRequest());
+
+        // Verify that once ignore-orientation-request has been set, it can be turned off by
+        // applying default value, e.g. the same display switches from large size to small size.
+        settingsEntry2.mIgnoreOrientationRequest = null;
+        mDisplayWindowSettings.applyRotationSettingsToDisplayLocked(dcIgnoreOrientation);
+        assertFalse(dcIgnoreOrientation.getIgnoreOrientationRequest());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 429a396a..de4b6fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -150,8 +150,8 @@
                 mProcess).build();
 
         // Use a new TestIWindow so we don't collect events for other windows
-        final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, activity, name,
-                ownerId, false, new TestIWindow());
+        final WindowState window = newWindowBuilder(name, TYPE_BASE_APPLICATION).setWindowToken(
+                activity).setOwnerId(ownerId).setClientWindow(new TestIWindow()).build();
         InputChannel channel = new InputChannel();
         window.openInputChannel(channel);
         window.mHasSurface = true;
@@ -249,7 +249,7 @@
                         mTarget.mDeferDragStateClosed = true;
                         mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
                         // Verify the drop event includes the drag surface
-                        mTarget.handleMotionEvent(false, 0, 0);
+                        mTarget.handleMotionEvent(false, mWindow.getDisplayId(), 0, 0);
                         final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
                         assertTrue(dropEvent.getDragSurface() != null);
 
@@ -296,7 +296,7 @@
                             0).getClipData().willParcelWithActivityInfo());
 
                     mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0);
-                    mTarget.handleMotionEvent(false, 0, 0);
+                    mTarget.handleMotionEvent(false, globalInterceptWindow.getDisplayId(), 0, 0);
                     mToken = globalInterceptWindow.mClient.asBinder();
 
                     // Verify the drop event is only sent for the global intercept window
@@ -334,8 +334,8 @@
                     try {
                         mTarget.mDeferDragStateClosed = true;
                         mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
-                        // // Verify the drop event does not have the drag flags
-                        mTarget.handleMotionEvent(false, 0, 0);
+                        // Verify the drop event does not have the drag flags
+                        mTarget.handleMotionEvent(false, mWindow.getDisplayId(), 0, 0);
                         final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
                         assertTrue(dropEvent.getDragFlags() == (View.DRAG_FLAG_GLOBAL
                                 | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
@@ -520,7 +520,7 @@
 
                     // Verify after consuming that the drag surface is relinquished
                     mTarget.reportDropWindow(otherWindow.mInputChannelToken, 0, 0);
-                    mTarget.handleMotionEvent(false, 0, 0);
+                    mTarget.handleMotionEvent(false, otherWindow.getDisplayId(), 0, 0);
                     mToken = otherWindow.mClient.asBinder();
                     mTarget.reportDropResult(otherIWindow, true);
 
@@ -551,7 +551,7 @@
 
                     // Verify after consuming that the drag surface is relinquished
                     mTarget.reportDropWindow(otherWindow.mInputChannelToken, 0, 0);
-                    mTarget.handleMotionEvent(false, 0, 0);
+                    mTarget.handleMotionEvent(false, otherWindow.getDisplayId(), 0, 0);
                     mToken = otherWindow.mClient.asBinder();
                     mTarget.reportDropResult(otherIWindow, false);
 
@@ -586,7 +586,8 @@
                 ClipData.newPlainText("label", "Test"), () -> {
                     // Trigger an unhandled drop and verify the global drag listener was called
                     mTarget.reportDropWindow(mWindow.mInputChannelToken, invalidXY, invalidXY);
-                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+                    mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(),
+                            invalidXY, invalidXY);
                     mTarget.reportDropResult(mWindow.mClient, false);
                     mTarget.onUnhandledDropCallback(true);
                     mToken = null;
@@ -610,7 +611,8 @@
                 ClipData.newPlainText("label", "Test"), () -> {
                     // Trigger an unhandled drop and verify the global drag listener was called
                     mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
-                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+                    mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(),
+                            invalidXY, invalidXY);
                     mTarget.onUnhandledDropCallback(true);
                     mToken = null;
                     try {
@@ -632,7 +634,8 @@
         startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
             // Trigger an unhandled drop and verify the global drag listener was not called
             mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
-            mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+            mTarget.handleMotionEvent(false /* keepHandling */, mDisplayContent.getDisplayId(),
+                    invalidXY, invalidXY);
             mToken = null;
             try {
                 verify(listener, never()).onUnhandledDrop(any(), any());
@@ -654,7 +657,8 @@
                 ClipData.newPlainText("label", "Test"), () -> {
                     // Trigger an unhandled drop and verify the global drag listener was called
                     mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
-                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
+                    mTarget.handleMotionEvent(false /* keepHandling */,
+                            mDisplayContent.getDisplayId(), invalidXY, invalidXY);
 
                     // Verify that the unhandled drop listener callback timeout has been scheduled
                     final Handler handler = mTarget.getHandler();
@@ -673,7 +677,8 @@
     private void doDragAndDrop(int flags, ClipData data, float dropX, float dropY) {
         startDrag(flags, data, () -> {
             mTarget.reportDropWindow(mWindow.mInputChannelToken, dropX, dropY);
-            mTarget.handleMotionEvent(false /* keepHandling */, dropX, dropY);
+            mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(), dropX,
+                    dropY);
             mToken = mWindow.mClient.asBinder();
         });
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java
index 7e1de47..51e0240 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxAttachInputTest.java
@@ -62,6 +62,8 @@
     private Letterbox mLetterbox;
     private LetterboxTest.SurfaceControlMocker mSurfaces;
 
+    private WindowState mWindowState;
+
     @Before
     public void setUp() throws Exception {
         mSurfaces = new LetterboxTest.SurfaceControlMocker();
@@ -72,6 +74,7 @@
         doReturn(false).when(letterboxOverrides).hasWallpaperBackgroundForLetterbox();
         doReturn(0).when(letterboxOverrides).getLetterboxWallpaperBlurRadiusPx();
         doReturn(0.5f).when(letterboxOverrides).getLetterboxWallpaperDarkScrimAlpha();
+        mWindowState = createWindowState();
         mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
                 mock(AppCompatReachabilityPolicy.class), letterboxOverrides,
                 () -> mock(SurfaceControl.class));
@@ -83,7 +86,6 @@
     public void testSurface_createdHasSlipperyInput_scrollingFromLetterboxDisabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
 
         assertNotNull(mSurfaces.top);
@@ -100,7 +102,6 @@
     public void testInputSurface_notCreated_scrollingFromLetterboxDisabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
 
         assertNull(mSurfaces.topInput);
@@ -111,7 +112,6 @@
     public void testSurface_createdHasNoInput_scrollingFromLetterboxEnabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
 
         assertNotNull(mSurfaces.top);
@@ -124,7 +124,6 @@
     public void testInputSurface_createdHasSpyInput_scrollingFromLetterboxEnabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
 
         assertNotNull(mSurfaces.topInput);
@@ -141,7 +140,6 @@
     public void testInputSurfaceOrigin_applied_scrollingFromLetterboxEnabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
 
         verify(mTransaction).setPosition(mSurfaces.topInput, -1000, -2000);
@@ -152,7 +150,6 @@
     public void testInputSurfaceOrigin_changeCausesReapply_scrollingFromLetterboxEnabled() {
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));
 
-        attachInput();
         applySurfaceChanges();
         clearInvocations(mTransaction);
         mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0));
@@ -166,13 +163,12 @@
 
     private void applySurfaceChanges() {
         mLetterbox.applySurfaceChanges(/* syncTransaction */ mTransaction,
-                /* pendingTransaction */ mTransaction);
+                /* pendingTransaction */ mTransaction, mWindowState);
     }
 
-    private void attachInput() {
+    private WindowState createWindowState() {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
         final WindowToken windowToken = createTestWindowToken(0, mDisplayContent);
-        WindowState windowState = createWindowState(attrs, windowToken);
-        mLetterbox.attachInput(windowState);
+        return createWindowState(attrs, windowToken);
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index 0baa517..a51a44f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -70,6 +70,7 @@
 
     private SurfaceControl mParentSurface = mock(SurfaceControl.class);
     private AppCompatLetterboxOverrides mLetterboxOverrides;
+    private WindowState mWindowState;
 
     @Before
     public void setUp() throws Exception {
@@ -81,6 +82,7 @@
         doReturn(false).when(mLetterboxOverrides).hasWallpaperBackgroundForLetterbox();
         doReturn(0).when(mLetterboxOverrides).getLetterboxWallpaperBlurRadiusPx();
         doReturn(0.5f).when(mLetterboxOverrides).getLetterboxWallpaperDarkScrimAlpha();
+        mWindowState = mock(WindowState.class);
         mLetterbox = new Letterbox(mSurfaces, StubTransaction::new,
                 mock(AppCompatReachabilityPolicy.class), mLetterboxOverrides, () -> mParentSurface);
         mTransaction = spy(StubTransaction.class);
@@ -320,7 +322,7 @@
 
     private void applySurfaceChanges() {
         mLetterbox.applySurfaceChanges(/* syncTransaction */ mTransaction,
-                /* pendingTransaction */ mTransaction);
+                /* pendingTransaction */ mTransaction, mWindowState);
     }
 
     static class SurfaceControlMocker implements Supplier<SurfaceControl.Builder> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 699ed02..7e62b89 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -1348,13 +1348,19 @@
                 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
         doReturn(rootTask3).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
 
-        // Set up user ids and visibility
+        // Set up child tasks inside root tasks and set some of them visible
+        final Task task1 = new TaskBuilder(mSupervisor).setOnTop(true).setParentTask(
+                rootTask1).build();
+        final Task task2 = new TaskBuilder(mSupervisor).setOnTop(true).setParentTask(
+                rootTask2).build();
+        final Task task3 = new TaskBuilder(mSupervisor).setOnTop(true).setParentTask(
+                rootTask3).build();
         rootTask1.mUserId = mRootWindowContainer.mCurrentUser;
         rootTask2.mUserId = mRootWindowContainer.mCurrentUser;
         rootTask3.mUserId = mRootWindowContainer.mCurrentUser;
-        rootTask1.mVisibleRequested = false;
-        rootTask2.mVisibleRequested = true;
-        rootTask3.mVisibleRequested = true;
+        doReturn(false).when(task1).isVisible();
+        doReturn(true).when(task2).isVisible();
+        doReturn(true).when(task3).isVisible();
 
         // Switch to a different user
         int currentUser = mRootWindowContainer.mCurrentUser;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 201ff51..6a738ae5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -391,7 +391,6 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_IMMERSIVE_APP_REPOSITIONING)
     @DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
     public void testRepositionLandscapeImmersiveAppWithDisplayCutout() {
         final int dw = 2100;
@@ -3783,7 +3782,6 @@
     }
 
     @Test
-    @EnableFlags(Flags.FLAG_IMMERSIVE_APP_REPOSITIONING)
     public void testImmersiveLetterboxAlignedToBottom_OverlappingNavbar() {
         assertLandscapeActivityAlignedToBottomWithNavbar(true /* immersive */);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 0cd036f..19c1ce2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -741,16 +741,16 @@
 
         // Not allowed because TaskFragments are not organized by the caller organizer.
         assertApplyTransactionDisallowed(mTransaction);
-        assertNull(mTaskFragment.getAdjacentTaskFragment());
-        assertNull(taskFragment2.getAdjacentTaskFragment());
+        assertFalse(mTaskFragment.hasAdjacentTaskFragment());
+        assertFalse(taskFragment2.hasAdjacentTaskFragment());
 
         mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                 "Test:TaskFragmentOrganizer" /* processName */);
 
         // Not allowed because TaskFragment2 is not organized by the caller organizer.
         assertApplyTransactionDisallowed(mTransaction);
-        assertNull(mTaskFragment.getAdjacentTaskFragment());
-        assertNull(taskFragment2.getAdjacentTaskFragment());
+        assertFalse(mTaskFragment.hasAdjacentTaskFragment());
+        assertFalse(taskFragment2.hasAdjacentTaskFragment());
 
         mTaskFragment.onTaskFragmentOrganizerRemoved();
         taskFragment2.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
@@ -758,14 +758,14 @@
 
         // Not allowed because mTaskFragment is not organized by the caller organizer.
         assertApplyTransactionDisallowed(mTransaction);
-        assertNull(mTaskFragment.getAdjacentTaskFragment());
-        assertNull(taskFragment2.getAdjacentTaskFragment());
+        assertFalse(mTaskFragment.hasAdjacentTaskFragment());
+        assertFalse(taskFragment2.hasAdjacentTaskFragment());
 
         mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                 "Test:TaskFragmentOrganizer" /* processName */);
 
         assertApplyTransactionAllowed(mTransaction);
-        assertEquals(taskFragment2, mTaskFragment.getAdjacentTaskFragment());
+        assertTrue(mTaskFragment.isAdjacentTo(taskFragment2));
     }
 
     @Test
@@ -790,14 +790,14 @@
 
         // Not allowed because TaskFragment is not organized by the caller organizer.
         assertApplyTransactionDisallowed(mTransaction);
-        assertEquals(taskFragment2, mTaskFragment.getAdjacentTaskFragment());
+        assertTrue(mTaskFragment.isAdjacentTo(taskFragment2));
 
         mTaskFragment.setTaskFragmentOrganizer(mOrganizerToken, 10 /* uid */,
                 "Test:TaskFragmentOrganizer" /* processName */);
 
         assertApplyTransactionAllowed(mTransaction);
-        assertNull(mTaskFragment.getAdjacentTaskFragment());
-        assertNull(taskFragment2.getAdjacentTaskFragment());
+        assertFalse(mTaskFragment.hasAdjacentTaskFragment());
+        assertFalse(taskFragment2.hasAdjacentTaskFragment());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index dafa96f..35a2546 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -365,7 +365,7 @@
 
         assertEquals(taskFragmentBounds, activity.getBounds());
         assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
-        assertEquals(taskFragment1, taskFragment0.getAdjacentTaskFragment());
+        assertTrue(taskFragment0.isAdjacentTo(taskFragment1));
         assertEquals(taskFragment1, taskFragment0.getCompanionTaskFragment());
         assertNotEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
 
@@ -381,7 +381,7 @@
         assertEquals(taskBounds, taskFragment0.getBounds());
         assertEquals(taskBounds, activity.getBounds());
         assertEquals(Configuration.EMPTY, taskFragment0.getRequestedOverrideConfiguration());
-        assertNull(taskFragment0.getAdjacentTaskFragment());
+        assertFalse(taskFragment0.hasAdjacentTaskFragment());
         assertNull(taskFragment0.getCompanionTaskFragment());
         assertEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
         // Because the whole Task is entering PiP, no need to record for future reparent.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 6655932..c6b2a6b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -33,6 +33,7 @@
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -45,12 +46,15 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.window.TaskSnapshot;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.window.flags.Flags;
+
 import com.google.android.collect.Sets;
 
 import org.junit.Test;
@@ -285,4 +289,27 @@
 
         assertFalse(success);
     }
+
+    @Test
+    @EnableFlags(Flags.FLAG_EXCLUDE_DRAWING_APP_THEME_SNAPSHOT_FROM_LOCK)
+    public void testRecordTaskSnapshot() {
+        spyOn(mWm.mTaskSnapshotController.mCache);
+        spyOn(mWm.mTaskSnapshotController);
+        doReturn(false).when(mWm.mTaskSnapshotController).shouldDisableSnapshots();
+
+        final WindowState normalWindow = createWindow(null,
+                FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow");
+        final TaskSnapshot snapshot = new TaskSnapshotPersisterTestBase.TaskSnapshotBuilder()
+                .setTopActivityComponent(normalWindow.mActivityRecord.mActivityComponent).build();
+        doReturn(snapshot).when(mWm.mTaskSnapshotController).snapshot(any());
+        final Task task = normalWindow.mActivityRecord.getTask();
+        mWm.mTaskSnapshotController.recordSnapshot(task);
+        verify(mWm.mTaskSnapshotController.mCache).putSnapshot(eq(task), any());
+        clearInvocations(mWm.mTaskSnapshotController.mCache);
+
+        normalWindow.mAttrs.flags |= FLAG_SECURE;
+        mWm.mTaskSnapshotController.recordSnapshot(task);
+        waitHandlerIdle(mWm.mH);
+        verify(mWm.mTaskSnapshotController.mCache).putSnapshot(eq(task), any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index da4c522..1281be51 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -909,8 +909,8 @@
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setAdjacentRoots(info1.token, info2.token);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
-        assertEquals(task1.getAdjacentTaskFragment(), task2);
-        assertEquals(task2.getAdjacentTaskFragment(), task1);
+        assertTrue(task1.isAdjacentTo(task2));
+        assertTrue(task2.isAdjacentTo(task1));
 
         wct = new WindowContainerTransaction();
         wct.setLaunchAdjacentFlagRoot(info1.token);
@@ -921,8 +921,8 @@
         wct.clearAdjacentRoots(info1.token);
         wct.clearLaunchAdjacentFlagRoot(info1.token);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
-        assertEquals(task1.getAdjacentTaskFragment(), null);
-        assertEquals(task2.getAdjacentTaskFragment(), null);
+        assertFalse(task1.hasAdjacentTaskFragment());
+        assertFalse(task2.hasAdjacentTaskFragment());
         assertEquals(dc.getDefaultTaskDisplayArea().mLaunchAdjacentFlagRootTask, null);
     }
 
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index fa4ec16..d3f98d1 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10596,6 +10596,8 @@
      *     <!-- Handover from 4G to IWLAN is not allowed if the device has capability in either IMS
      *     or EIMS-->
      *     <item value="source=EUTRAN, target=IWLAN, type=disallowed, capabilities=IMS|EIMS"/>
+     *     <!-- Handover from IWLAN to 5G is not allowed if the device is incall. -->
+     *     <item value="source=IWLAN, target=NGRAN, incall=true, type=disallowed"/>
      *     <!-- Handover is always allowed in any condition. -->
      *     <item value="source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN|UNKNOWN,
      *         target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"/>
diff --git a/telephony/java/android/telephony/satellite/ISatelliteSupportedStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteSupportedStateCallback.aidl
deleted file mode 100644
index 0455090..0000000
--- a/telephony/java/android/telephony/satellite/ISatelliteSupportedStateCallback.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.satellite;
-
-/**
- * Interface for satellite supported state change callback.
- * @hide
- */
-oneway interface ISatelliteSupportedStateCallback {
-    /**
-     * Called when satellite supported state has changed.
-     *
-     * @param supoprted Whether satellite is supported or not.
-     */
-    void onSatelliteSupportedStateChanged(in boolean supported);
-}
-
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index cf807a2..b885b30 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -43,6 +43,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyRegistryManager;
 
+import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.IVoidConsumer;
@@ -96,8 +97,8 @@
     private static final ConcurrentHashMap<SatelliteCapabilitiesCallback,
             ISatelliteCapabilitiesCallback>
             sSatelliteCapabilitiesCallbackMap = new ConcurrentHashMap<>();
-    private static final ConcurrentHashMap<SatelliteSupportedStateCallback,
-            ISatelliteSupportedStateCallback> sSatelliteSupportedStateCallbackMap =
+    private static final ConcurrentHashMap<Consumer<Boolean>,
+            IBooleanConsumer> sSatelliteSupportedStateCallbackMap =
             new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallback,
             ISatelliteCommunicationAllowedStateCallback>
@@ -781,6 +782,28 @@
     @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String ACTION_SATELLITE_START_NON_EMERGENCY_SESSION =
             "android.telephony.satellite.action.SATELLITE_START_NON_EMERGENCY_SESSION";
+
+    /**
+     * Application level {@link android.content.pm.PackageManager.Property} tag that represents
+     * whether the application supports P2P SMS over carrier roaming satellite which needs manual
+     * trigger to connect to satellite. The messaging applications that supports P2P SMS over
+     * carrier roaming satellite should set value of this property to {@code true}.
+     *
+     * <p><b>Syntax:</b>
+     * <pre>
+     * &lt;application&gt;
+     *   &lt;property
+     *     android:name="android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT"
+     *     android:value="true"/&gt;
+     * &lt;/application&gt;
+     * </pre>
+     * @hide
+     */
+    @SystemApi
+    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
+    public static final String PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT =
+            "android.telephony.satellite.PROPERTY_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
+
     /**
      * Meta-data represents whether the application supports P2P SMS over carrier roaming satellite
      * which needs manual trigger to connect to satellite. The messaging applications that supports
@@ -794,8 +817,6 @@
      * }
      * @hide
      */
-    @SystemApi
-    @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     public static final String METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT =
             "android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
 
@@ -3303,7 +3324,7 @@
      * @param executor The executor on which the callback will be called.
      * @param callback The callback to handle the satellite supoprted state changed event.
      *
-     * @return The {@link SatelliteResult} result of the operation.
+     * @return The result of the operation.
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
@@ -3313,23 +3334,20 @@
     @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     @SatelliteResult public int registerForSupportedStateChanged(
-            @NonNull @CallbackExecutor Executor executor,
-            @NonNull SatelliteSupportedStateCallback callback) {
+            @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
         Objects.requireNonNull(executor);
         Objects.requireNonNull(callback);
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                ISatelliteSupportedStateCallback internalCallback =
-                        new ISatelliteSupportedStateCallback.Stub() {
-                            @Override
-                            public void onSatelliteSupportedStateChanged(boolean supported) {
-                                executor.execute(() -> Binder.withCleanCallingIdentity(
-                                        () -> callback.onSatelliteSupportedStateChanged(
-                                                supported)));
-                            }
-                        };
+                IBooleanConsumer internalCallback = new IBooleanConsumer.Stub() {
+                    @Override
+                    public void accept(boolean supported) {
+                        executor.execute(() -> Binder.withCleanCallingIdentity(
+                                () -> callback.accept(supported)));
+                    }
+                };
                 sSatelliteSupportedStateCallbackMap.put(callback, internalCallback);
                 return telephony.registerForSatelliteSupportedStateChanged(
                         internalCallback);
@@ -3348,7 +3366,7 @@
      * If callback was not registered before, the request will be ignored.
      *
      * @param callback The callback that was passed to
-     * {@link #registerForSupportedStateChanged(Executor, SatelliteSupportedStateCallback)}
+     * {@link #registerForSupportedStateChanged(Executor, Consumer)}
      *
      * @throws SecurityException if the caller doesn't have required permission.
      * @throws IllegalStateException if the Telephony process is not currently available.
@@ -3357,10 +3375,9 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
     @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
-    public void unregisterForSupportedStateChanged(
-            @NonNull SatelliteSupportedStateCallback callback) {
+    public void unregisterForSupportedStateChanged(@NonNull Consumer<Boolean> callback) {
         Objects.requireNonNull(callback);
-        ISatelliteSupportedStateCallback internalCallback =
+        IBooleanConsumer internalCallback =
                 sSatelliteSupportedStateCallbackMap.remove(callback);
 
         try {
diff --git a/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
index d7fa3c9..8fd05fc 100644
--- a/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
+++ b/telephony/java/android/telephony/satellite/SatelliteModemEnableRequestAttributes.java
@@ -29,7 +29,8 @@
 /**
  * SatelliteModemEnableRequestAttributes is used to pack info needed by modem to allow carrier to
  * roam to satellite.
- *
+ * These attributes will be used by modem to decide how they should act,
+ * decide how to attach to the network and whether to enable or disable satellite mode.
  * @hide
  */
 @SystemApi
@@ -42,32 +43,38 @@
      * {@code true} to enable demo mode and {@code false} to disable. When disabling satellite,
      * {@code mIsDemoMode} is always considered as {@code false} by Telephony.
      */
-    private final boolean mIsDemoMode;
+    private final boolean mIsForDemoMode;
     /**
      * {@code true} means satellite is enabled for emergency mode, {@code false} otherwise. When
      * disabling satellite, {@code isEmergencyMode} is always considered as {@code false} by
      * Telephony.
      */
-    private final boolean mIsEmergencyMode;
+    private final boolean mIsForEmergencyMode;
 
     /** The subscription related info */
     @NonNull private final SatelliteSubscriptionInfo mSatelliteSubscriptionInfo;
 
     /**
-     * @hide
+     * Constructor for SatelliteModemEnableRequestAttributes objects.
+     * @param isEnabled {@code true} to enable satellite and {@code false} to disable satellite
+     * @param isForDemoMode {@code true} to enable demo mode and {@code false} to disable.
+     * @param isForEmergencyMode {@code true} means satellite is enabled for emergency mode,
+     *                        {@code false} otherwise.
+     * @param satelliteSubscriptionInfo satellite subscription related info.
      */
-    public SatelliteModemEnableRequestAttributes(boolean isEnabled, boolean isDemoMode,
-            boolean isEmergencyMode, @NonNull SatelliteSubscriptionInfo satelliteSubscriptionInfo) {
+    public SatelliteModemEnableRequestAttributes(boolean isEnabled, boolean isForDemoMode,
+            boolean isForEmergencyMode,
+            @NonNull SatelliteSubscriptionInfo satelliteSubscriptionInfo) {
         mIsEnabled = isEnabled;
-        mIsDemoMode = isDemoMode;
-        mIsEmergencyMode = isEmergencyMode;
+        mIsForDemoMode = isForDemoMode;
+        mIsForEmergencyMode = isForEmergencyMode;
         mSatelliteSubscriptionInfo = satelliteSubscriptionInfo;
     }
 
     private SatelliteModemEnableRequestAttributes(Parcel in) {
         mIsEnabled = in.readBoolean();
-        mIsDemoMode = in.readBoolean();
-        mIsEmergencyMode = in.readBoolean();
+        mIsForDemoMode = in.readBoolean();
+        mIsForEmergencyMode = in.readBoolean();
         mSatelliteSubscriptionInfo = in.readParcelable(
                 SatelliteSubscriptionInfo.class.getClassLoader(), SatelliteSubscriptionInfo.class);
     }
@@ -80,8 +87,8 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeBoolean(mIsEnabled);
-        dest.writeBoolean(mIsDemoMode);
-        dest.writeBoolean(mIsEmergencyMode);
+        dest.writeBoolean(mIsForDemoMode);
+        dest.writeBoolean(mIsForEmergencyMode);
         mSatelliteSubscriptionInfo.writeToParcel(dest, flags);
     }
 
@@ -102,8 +109,8 @@
     public String toString() {
         return (new StringBuilder()).append("SatelliteModemEnableRequestAttributes{")
                 .append(", mIsEnabled=").append(mIsEnabled)
-                .append(", mIsDemoMode=").append(mIsDemoMode)
-                .append(", mIsDemoMode=").append(mIsDemoMode)
+                .append(", mIsForDemoMode=").append(mIsForDemoMode)
+                .append(", mIsForEmergencyMode=").append(mIsForEmergencyMode)
                 .append("mSatelliteSubscriptionInfo=").append(mSatelliteSubscriptionInfo)
                 .append("}")
                 .toString();
@@ -114,14 +121,15 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         SatelliteModemEnableRequestAttributes that = (SatelliteModemEnableRequestAttributes) o;
-        return mIsEnabled == that.mIsEnabled && mIsDemoMode == that.mIsDemoMode
-                && mIsEmergencyMode == that.mIsEmergencyMode && mSatelliteSubscriptionInfo.equals(
-                that.mSatelliteSubscriptionInfo);
+        return mIsEnabled == that.mIsEnabled && mIsForDemoMode == that.mIsForDemoMode
+                && mIsForEmergencyMode == that.mIsForEmergencyMode
+                && mSatelliteSubscriptionInfo.equals(that.mSatelliteSubscriptionInfo);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mIsEnabled, mIsDemoMode, mIsEmergencyMode, mSatelliteSubscriptionInfo);
+        return Objects.hash(mIsEnabled, mIsForDemoMode, mIsForEmergencyMode,
+                mSatelliteSubscriptionInfo);
     }
 
 
@@ -138,8 +146,8 @@
      * Get whether satellite modem is enabled for demo mode.
      * @return {@code true} if the request is to enable demo mode, else {@code false}.
      */
-    public boolean isDemoMode() {
-        return mIsDemoMode;
+    public boolean isForDemoMode() {
+        return mIsForDemoMode;
     }
 
     /**
@@ -147,8 +155,8 @@
      * @return {@code true} if the request is to enable satellite for emergency mode,
      * else {@code false}.
      */
-    public boolean isEmergencyMode() {
-        return mIsEmergencyMode;
+    public boolean isForEmergencyMode() {
+        return mIsForEmergencyMode;
     }
 
 
diff --git a/telephony/java/android/telephony/satellite/SatellitePosition.java b/telephony/java/android/telephony/satellite/SatellitePosition.java
index b8d138f..46af5c8 100644
--- a/telephony/java/android/telephony/satellite/SatellitePosition.java
+++ b/telephony/java/android/telephony/satellite/SatellitePosition.java
@@ -16,6 +16,7 @@
 package android.telephony.satellite;
 
 import android.annotation.FlaggedApi;
+import android.annotation.FloatRange;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -65,9 +66,9 @@
      *
      * @param longitudeDegree The longitude of the satellite in degrees.
      * @param altitudeKm  The altitude of the satellite in kilometers.
-     * @hide
      */
-    public SatellitePosition(double longitudeDegree, double altitudeKm) {
+    public SatellitePosition(@FloatRange(from = -180, to = 180) double longitudeDegree,
+            @FloatRange(from = 0.0) double altitudeKm) {
         mLongitudeDegree = longitudeDegree;
         mAltitudeKm = altitudeKm;
     }
@@ -106,6 +107,7 @@
      *
      * @return The longitude of the satellite.
      */
+    @FloatRange(from = -180, to = 180)
     public double getLongitudeDegrees() {
         return mLongitudeDegree;
     }
@@ -115,6 +117,7 @@
      *
      * @return The altitude of the satellite.
      */
+    @FloatRange(from = 0.0)
     public double getAltitudeKm() {
         return mAltitudeKm;
     }
diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
index 8427057..6e33995 100644
--- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
+++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java
@@ -30,8 +30,6 @@
 import java.util.Objects;
 
 /**
- * SatelliteSubscriberInfo
- *
  * Satellite Gateway client will use these subscriber ids to register with satellite gateway service
  * which identify user subscription with unique subscriber ids. These subscriber ids can be any
  * unique value like iccid, imsi or msisdn which is decided based upon carrier requirements.
@@ -52,16 +50,16 @@
     private int mSubId;
 
     /** SubscriberId format is the ICCID. */
-    public static final int ICCID = 0;
+    public static final int SUBSCRIBER_ID_TYPE_ICCID = 0;
     /** SubscriberId format is the 6 digit of IMSI + MSISDN. */
-    public static final int IMSI_MSISDN = 1;
+    public static final int SUBSCRIBER_ID_TYPE_IMSI_MSISDN = 1;
 
     /** Type of subscriber id */
     @SubscriberIdType private int mSubscriberIdType;
     /** @hide */
-    @IntDef(prefix = "SubscriberId_Type_", value = {
-            ICCID,
-            IMSI_MSISDN
+    @IntDef(prefix = "SUBSCRIBER_ID_TYPE_", value = {
+            SUBSCRIBER_ID_TYPE_ICCID,
+            SUBSCRIBER_ID_TYPE_IMSI_MSISDN
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SubscriberIdType {}
diff --git a/telephony/java/android/telephony/satellite/SatelliteSupportedStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteSupportedStateCallback.java
deleted file mode 100644
index 5487eb6..0000000
--- a/telephony/java/android/telephony/satellite/SatelliteSupportedStateCallback.java
+++ /dev/null
@@ -1,39 +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.telephony.satellite;
-
-import android.annotation.FlaggedApi;
-import android.annotation.SystemApi;
-
-import com.android.internal.telephony.flags.Flags;
-
-/**
- * A callback class for monitoring satellite supported state change events.
- *
- * @hide
- */
-@SystemApi
-@FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS)
-public interface SatelliteSupportedStateCallback {
-    /**
-     * Called when satellite supported state changes.
-     *
-     * @param supported The new supported state. {@code true} means satellite is supported,
-     * {@code false} means satellite is not supported.
-     */
-    void onSatelliteSupportedStateChanged(boolean supported);
-}
diff --git a/telephony/java/android/telephony/satellite/SystemSelectionSpecifier.java b/telephony/java/android/telephony/satellite/SystemSelectionSpecifier.java
index 61e1e5f..ca69984 100644
--- a/telephony/java/android/telephony/satellite/SystemSelectionSpecifier.java
+++ b/telephony/java/android/telephony/satellite/SystemSelectionSpecifier.java
@@ -27,11 +27,17 @@
 
 import com.android.internal.telephony.flags.Flags;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
 /**
+ * This class defines the information that modem will use to decide which satellites it should
+ * attach to and how it should scan for the signal from the chosen satellites.
+ * Moreover, it also provides the customized information {@code mTagIds} to provide the flexibility
+ * for OEMs and vendors to define more info that they need for communicating with satellites like
+ * how modem should control the power to meet the requirement of local authorities.
  * @hide
  */
 @SystemApi
@@ -42,20 +48,20 @@
     @NonNull private String mMccMnc;
 
     /** The frequency bands to scan. Maximum length of the vector is 8. */
-    @NonNull private IntArray mBands;
+    @NonNull private int[] mBands;
 
     /**
      * The radio channels to scan as defined in 3GPP TS 25.101 and 36.101.
      * Maximum length of the vector is 32.
      */
-    @NonNull private IntArray mEarfcns;
+    @NonNull private int[] mEarfcns;
 
     /* The list of satellites configured for the current location */
     @Nullable
-    private SatelliteInfo[] mSatelliteInfos;
+    private List<SatelliteInfo> mSatelliteInfos;
 
     /* The list of tag IDs associated with the current location */
-    @Nullable private IntArray mTagIds;
+    @Nullable private int[] mTagIds;
 
     /**
      * @hide
@@ -64,10 +70,84 @@
             @NonNull IntArray earfcns, @Nullable SatelliteInfo[] satelliteInfos,
             @Nullable IntArray tagIds) {
         mMccMnc = mccmnc;
-        mBands = bands;
-        mEarfcns = earfcns;
-        mSatelliteInfos = satelliteInfos;
-        mTagIds = tagIds;
+        mBands = bands.toArray();
+        mEarfcns = earfcns.toArray();
+        mSatelliteInfos = Arrays.stream(satelliteInfos).toList();
+        mTagIds = tagIds.toArray();
+    }
+
+    /**
+     * @hide
+     */
+    public SystemSelectionSpecifier(Builder builder) {
+        mMccMnc = builder.mMccMnc;
+        mBands = builder.mBands;
+        mEarfcns = builder.mEarfcns;
+        mSatelliteInfos = builder.mSatelliteInfos;
+        mTagIds = builder.mTagIds;
+    }
+
+    /**
+     * Builder class for constructing SystemSelectionSpecifier objects
+     */
+    public static final class Builder {
+        @NonNull private String mMccMnc;
+        @NonNull private int[] mBands;
+        @NonNull private int[] mEarfcns;
+        private List<SatelliteInfo> mSatelliteInfos;
+        @Nullable private int[] mTagIds;
+
+        /** Set network plmn associated with the channel and return the Builder class. */
+        @NonNull
+        public Builder setMccMnc(@NonNull String mccMnc) {
+            this.mMccMnc = mccMnc;
+            return this;
+        }
+
+        /**
+         * Set frequency bands to scan and return the Builder class.
+         * Maximum length of the vector is 8.
+         */
+        @NonNull
+        public Builder setBands(@NonNull int[] bands) {
+            this.mBands = bands;
+            return this;
+        }
+
+        /**
+         * Set radio channels to scan as defined in 3GPP TS 25.101 and 36.101
+         * and returns the Builder class.
+         * Maximum length if the vector is 32.
+         */
+        @NonNull
+        public Builder setEarfcns(@NonNull int[] earfcns) {
+            this.mEarfcns = earfcns;
+            return this;
+        }
+
+        /**
+         * Set list of satellites configured for the current location and return the Builder class.
+         */
+        @NonNull
+        public Builder setSatelliteInfos(@NonNull List<SatelliteInfo> satelliteInfos) {
+            this.mSatelliteInfos = satelliteInfos;
+            return this;
+        }
+
+        /**
+         * Set list of tag IDs associated with the current location and return the Builder class.
+         */
+        @NonNull
+        public Builder setTagIds(@NonNull int[] tagIds) {
+            this.mTagIds = tagIds;
+            return this;
+        }
+
+        /** Return SystemSelectionSpecifier object */
+        @NonNull
+        public SystemSelectionSpecifier build() {
+            return new SystemSelectionSpecifier(this);
+        }
     }
 
     private SystemSelectionSpecifier(Parcel in) {
@@ -84,30 +164,30 @@
         mMccMnc = TextUtils.emptyIfNull(mMccMnc);
         out.writeString8(mMccMnc);
 
-        if (mBands != null && mBands.size() > 0) {
-            out.writeInt(mBands.size());
-            for (int i = 0; i < mBands.size(); i++) {
-                out.writeInt(mBands.get(i));
+        if (mBands != null && mBands.length > 0) {
+            out.writeInt(mBands.length);
+            for (int i = 0; i < mBands.length; i++) {
+                out.writeInt(mBands[i]);
             }
         } else {
             out.writeInt(0);
         }
 
-        if (mEarfcns != null && mEarfcns.size() > 0) {
-            out.writeInt(mEarfcns.size());
-            for (int i = 0; i < mEarfcns.size(); i++) {
-                out.writeInt(mEarfcns.get(i));
+        if (mEarfcns != null && mEarfcns.length > 0) {
+            out.writeInt(mEarfcns.length);
+            for (int i = 0; i < mEarfcns.length; i++) {
+                out.writeInt(mEarfcns[i]);
             }
         } else {
             out.writeInt(0);
         }
 
-        out.writeTypedArray(mSatelliteInfos, flags);
+        out.writeTypedArray(mSatelliteInfos.toArray(new SatelliteInfo[0]), flags);
 
         if (mTagIds != null) {
-            out.writeInt(mTagIds.size());
-            for (int i = 0; i < mTagIds.size(); i++) {
-                out.writeInt(mTagIds.get(i));
+            out.writeInt(mTagIds.length);
+            for (int i = 0; i < mTagIds.length; i++) {
+                out.writeInt(mTagIds[i]);
             }
         } else {
             out.writeInt(0);
@@ -135,9 +215,9 @@
         sb.append(",");
 
         sb.append("bands:");
-        if (mBands != null && mBands.size() > 0) {
-            for (int i = 0; i < mBands.size(); i++) {
-                sb.append(mBands.get(i));
+        if (mBands != null && mBands.length > 0) {
+            for (int i = 0; i < mBands.length; i++) {
+                sb.append(mBands[i]);
                 sb.append(",");
             }
         } else {
@@ -145,9 +225,9 @@
         }
 
         sb.append("earfcs:");
-        if (mEarfcns != null && mEarfcns.size() > 0) {
-            for (int i = 0; i < mEarfcns.size(); i++) {
-                sb.append(mEarfcns.get(i));
+        if (mEarfcns != null && mEarfcns.length > 0) {
+            for (int i = 0; i < mEarfcns.length; i++) {
+                sb.append(mEarfcns[i]);
                 sb.append(",");
             }
         } else {
@@ -155,7 +235,7 @@
         }
 
         sb.append("mSatelliteInfos:");
-        if (mSatelliteInfos != null && mSatelliteInfos.length > 0) {
+        if (mSatelliteInfos != null && mSatelliteInfos.size() > 0) {
             for (SatelliteInfo satelliteInfo : mSatelliteInfos) {
                 sb.append(satelliteInfo);
                 sb.append(",");
@@ -165,9 +245,9 @@
         }
 
         sb.append("mTagIds:");
-        if (mTagIds != null && mTagIds.size() > 0) {
-            for (int i = 0; i < mTagIds.size(); i++) {
-                sb.append(mTagIds.get(i));
+        if (mTagIds != null && mTagIds.length > 0) {
+            for (int i = 0; i < mTagIds.length; i++) {
+                sb.append(mTagIds[i]);
                 sb.append(",");
             }
         } else {
@@ -183,16 +263,16 @@
         if (o == null || getClass() != o.getClass()) return false;
         SystemSelectionSpecifier that = (SystemSelectionSpecifier) o;
         return Objects.equals(mMccMnc, that.mMccMnc)
-                && Objects.equals(mBands, that.mBands)
-                && Objects.equals(mEarfcns, that.mEarfcns)
-                && (mSatelliteInfos == null ? that.mSatelliteInfos == null : Arrays.equals(
-                mSatelliteInfos, that.mSatelliteInfos))
-                && Objects.equals(mTagIds, that.mTagIds);
+                && Arrays.equals(mBands, that.mBands)
+                && Arrays.equals(mEarfcns, that.mEarfcns)
+                && (mSatelliteInfos == null ? that.mSatelliteInfos == null :
+                mSatelliteInfos.equals(that.mSatelliteInfos))
+                && Arrays.equals(mTagIds, that.mTagIds);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mMccMnc, mBands, mEarfcns);
+        return Objects.hash(mMccMnc, Arrays.hashCode(mBands), Arrays.hashCode(mEarfcns));
     }
 
     /** Return network plmn associated with channel information. */
@@ -203,9 +283,10 @@
     /**
      * Return the frequency bands to scan.
      * Maximum length of the vector is 8.
+     * Refer specification 3GPP TS 36.101 for detailed information on frequency bands.
      */
     @NonNull public int[] getBands() {
-        return mBands.toArray();
+        return mBands;
     }
 
     /**
@@ -213,13 +294,13 @@
      * Maximum length of the vector is 32.
      */
     @NonNull public int[] getEarfcns() {
-        return mEarfcns.toArray();
+        return mEarfcns;
     }
 
     /** Return the list of satellites configured for the current location. */
     @NonNull
     public List<SatelliteInfo> getSatelliteInfos() {
-        return Arrays.stream(mSatelliteInfos).toList();
+        return mSatelliteInfos;
     }
 
     /**
@@ -229,34 +310,36 @@
      */
     @NonNull
     public int[] getTagIds() {
-        return mTagIds.toArray();
+        return mTagIds;
     }
 
     private void readFromParcel(Parcel in) {
         mMccMnc = in.readString();
 
-        mBands = new IntArray();
         int numBands = in.readInt();
+        mBands = new int[numBands];
         if (numBands > 0) {
             for (int i = 0; i < numBands; i++) {
-                mBands.add(in.readInt());
+                mBands[i] = in.readInt();
             }
         }
 
-        mEarfcns = new IntArray();
         int numEarfcns = in.readInt();
+        mEarfcns = new int[numEarfcns];
         if (numEarfcns > 0) {
             for (int i = 0; i < numEarfcns; i++) {
-                mEarfcns.add(in.readInt());
+                mEarfcns[i] = in.readInt();
             }
         }
 
-        mSatelliteInfos = in.createTypedArray(SatelliteInfo.CREATOR);
+        mSatelliteInfos = new ArrayList<>();
+        in.readList(mSatelliteInfos, SatelliteInfo.class.getClassLoader(), SatelliteInfo.class);
 
         int numTagIds = in.readInt();
+        mTagIds = new int[numTagIds];
         if (numTagIds > 0) {
             for (int i = 0; i < numTagIds; i++) {
-                mTagIds.add(in.readInt());
+                mTagIds[i] = in.readInt();
             }
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 74d9204..aa57730 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -74,7 +74,6 @@
 import android.telephony.satellite.ISatelliteDisallowedReasonsCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteSupportedStateCallback;
 import android.telephony.satellite.ISatelliteModemStateCallback;
 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
@@ -3425,8 +3424,7 @@
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    int registerForSatelliteSupportedStateChanged(
-            in ISatelliteSupportedStateCallback callback);
+    int registerForSatelliteSupportedStateChanged(in IBooleanConsumer callback);
 
     /**
      * Unregisters for supported state changed from satellite modem.
@@ -3436,8 +3434,7 @@
      */
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
-    void unregisterForSatelliteSupportedStateChanged(
-            in ISatelliteSupportedStateCallback callback);
+    void unregisterForSatelliteSupportedStateChanged(in IBooleanConsumer callback);
 
     /**
      * Registers for satellite communication allowed state changed.
diff --git a/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java b/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java
index 34f0c19..fe9f636 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java
@@ -76,6 +76,7 @@
     private ActivityTestRule<EmptyActivity> mEmptyActivityRule =
             new ActivityTestRule<>(EmptyActivity.class, false , true);
 
+
     @Before
     public void setUp() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -163,7 +164,7 @@
         // of that state.
         for (int i = 0; i < uiStates.size(); i++) {
             StateTracker.StateData stateData = uiStates.get(i);
-            if (stateData.mWidgetCategory.equals(AppJankStats.ANIMATION)) {
+            if (stateData.mWidgetCategory.equals(AppJankStats.WIDGET_CATEGORY_ANIMATION)) {
                 assertNotEquals(Long.MAX_VALUE, stateData.mVsyncIdEnd);
             }
         }
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java b/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
index 30c568b..c905957 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
@@ -215,7 +215,8 @@
         assertEquals(jankStats.getJankyFrameCount() * 2, pendingStat.getJankyFrames());
         assertEquals(jankStats.getTotalFrameCount() * 2, pendingStat.getTotalFrames());
 
-        int[] originalHistogramBuckets = jankStats.getFrameOverrunHistogram().getBucketCounters();
+        int[] originalHistogramBuckets =
+                jankStats.getRelativeFrameTimeHistogram().getBucketCounters();
         int[] frameOverrunBuckets = pendingStat.getFrameOverrunBuckets();
 
         for (int i = 0; i < frameOverrunBuckets.length; i++) {
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java b/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java
index 0b4d97e..df92898 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java
@@ -17,7 +17,7 @@
 package android.app.jank.tests;
 
 import android.app.jank.AppJankStats;
-import android.app.jank.FrameOverrunHistogram;
+import android.app.jank.RelativeFrameTimeHistogram;
 
 public class JankUtils {
     private static final int APP_ID = 25;
@@ -29,8 +29,8 @@
         AppJankStats jankStats = new AppJankStats(
                 /*App Uid*/APP_ID,
                 /*Widget Id*/"test widget id",
-                /*Widget Category*/AppJankStats.SCROLL,
-                /*Widget State*/AppJankStats.SCROLLING,
+                /*Widget Category*/AppJankStats.WIDGET_CATEGORY_SCROLL,
+                /*Widget State*/AppJankStats.WIDGET_STATE_SCROLLING,
                 /*Total Frames*/100,
                 /*Janky Frames*/25,
                 getOverrunHistogram()
@@ -41,12 +41,12 @@
     /**
      * Returns a mock histogram to be used with an AppJankStats object.
      */
-    public static FrameOverrunHistogram getOverrunHistogram() {
-        FrameOverrunHistogram overrunHistogram = new FrameOverrunHistogram();
-        overrunHistogram.addFrameOverrunMillis(-2);
-        overrunHistogram.addFrameOverrunMillis(1);
-        overrunHistogram.addFrameOverrunMillis(5);
-        overrunHistogram.addFrameOverrunMillis(25);
+    public static RelativeFrameTimeHistogram getOverrunHistogram() {
+        RelativeFrameTimeHistogram overrunHistogram = new RelativeFrameTimeHistogram();
+        overrunHistogram.addRelativeFrameTimeMillis(-2);
+        overrunHistogram.addRelativeFrameTimeMillis(1);
+        overrunHistogram.addRelativeFrameTimeMillis(5);
+        overrunHistogram.addRelativeFrameTimeMillis(25);
         return overrunHistogram;
     }
 }
diff --git a/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java b/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java
index 5fff460..71796d6 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java
@@ -45,8 +45,8 @@
      */
     public void simulateAnimationStarting() {
         if (jankTrackerCreated()) {
-            mJankTracker.addUiState(AppJankStats.ANIMATION,
-                    Integer.toString(this.getId()), AppJankStats.ANIMATING);
+            mJankTracker.addUiState(AppJankStats.WIDGET_CATEGORY_ANIMATION,
+                    Integer.toString(this.getId()), AppJankStats.WIDGET_STATE_ANIMATING);
         }
     }
 
@@ -55,8 +55,8 @@
      */
     public void simulateAnimationEnding() {
         if (jankTrackerCreated()) {
-            mJankTracker.removeUiState(AppJankStats.ANIMATION,
-                    Integer.toString(this.getId()), AppJankStats.ANIMATING);
+            mJankTracker.removeUiState(AppJankStats.WIDGET_CATEGORY_ANIMATION,
+                    Integer.toString(this.getId()), AppJankStats.WIDGET_STATE_ANIMATING);
         }
     }
 
diff --git a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
index 700856c..14c8de8 100644
--- a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
+++ b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/GraphicsActivity.java
@@ -819,7 +819,7 @@
     private List<Float> getExpectedFrameRateForCompatibility(int compatibility) {
         assumeTrue("**** testSurfaceControlFrameRateCompatibility SKIPPED for compatibility "
                         + compatibility,
-                compatibility == Surface.FRAME_RATE_COMPATIBILITY_GTE);
+                compatibility == Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST);
 
         Display display = getDisplay();
         List<Float> expectedFrameRates = getRefreshRates(display.getMode(), display)
diff --git a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
index 4d48276..f1d4dc6 100644
--- a/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
+++ b/tests/CtsSurfaceControlTestsStaging/src/main/java/android/view/surfacecontroltests/SurfaceControlTest.java
@@ -85,7 +85,8 @@
     @Test
     public void testSurfaceControlFrameRateCompatibilityGte() throws InterruptedException {
         GraphicsActivity activity = mActivityRule.getActivity();
-        activity.testSurfaceControlFrameRateCompatibility(Surface.FRAME_RATE_COMPATIBILITY_GTE);
+        activity.testSurfaceControlFrameRateCompatibility(
+                Surface.FRAME_RATE_COMPATIBILITY_AT_LEAST);
     }
 
     @Test
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
index 2e7b207..0824874 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -28,7 +28,9 @@
 import android.tools.helpers.SYSTEMUI_PACKAGE
 import android.tools.traces.parsers.WindowManagerStateHelper
 import android.tools.traces.wm.WindowingMode
+import android.view.KeyEvent.KEYCODE_EQUALS
 import android.view.KeyEvent.KEYCODE_LEFT_BRACKET
+import android.view.KeyEvent.KEYCODE_MINUS
 import android.view.KeyEvent.KEYCODE_RIGHT_BRACKET
 import android.view.KeyEvent.META_META_ON
 import android.view.WindowInsets
@@ -146,10 +148,19 @@
     }
 
     /** Click maximise button on the app header for the given app. */
-    fun maximiseDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
-        val caption = getCaptionForTheApp(wmHelper, device)
-        val maximizeButton = getMaximizeButtonForTheApp(caption)
-        maximizeButton.click()
+    fun maximiseDesktopApp(
+        wmHelper: WindowManagerStateHelper,
+        device: UiDevice,
+        usingKeyboard: Boolean = false
+    ) {
+        if (usingKeyboard) {
+            val keyEventHelper = KeyEventHelper(getInstrumentation())
+            keyEventHelper.press(KEYCODE_EQUALS, META_META_ON)
+        } else {
+            val caption = getCaptionForTheApp(wmHelper, device)
+            val maximizeButton = getMaximizeButtonForTheApp(caption)
+            maximizeButton.click()
+        }
         wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
     }
 
@@ -160,10 +171,21 @@
             ?: error("Unable to find resource $MINIMIZE_BUTTON_VIEW\n")
     }
 
-    fun minimizeDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice, isPip: Boolean = false) {
-        val caption = getCaptionForTheApp(wmHelper, device)
-        val minimizeButton = getMinimizeButtonForTheApp(caption)
-        minimizeButton.click()
+    fun minimizeDesktopApp(
+        wmHelper: WindowManagerStateHelper,
+        device: UiDevice,
+        isPip: Boolean = false,
+        usingKeyboard: Boolean = false,
+    ) {
+        if (usingKeyboard) {
+            val keyEventHelper = KeyEventHelper(getInstrumentation())
+            keyEventHelper.press(KEYCODE_MINUS, META_META_ON)
+        } else {
+            val caption = getCaptionForTheApp(wmHelper, device)
+            val minimizeButton = getMinimizeButtonForTheApp(caption)
+            minimizeButton.click()
+        }
+
         wmHelper
             .StateSyncBuilder()
             .withAppTransitionIdle()
@@ -226,8 +248,7 @@
         toLeft: Boolean,
     ) {
         val bracketKey = if (toLeft) KEYCODE_LEFT_BRACKET else KEYCODE_RIGHT_BRACKET
-        keyEventHelper.actionDown(bracketKey, META_META_ON)
-        keyEventHelper.actionUp(bracketKey, META_META_ON)
+        keyEventHelper.press(bracketKey, META_META_ON)
         waitAndVerifySnapResize(wmHelper, context, toLeft)
     }
 
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/KeyEventHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/KeyEventHelper.kt
index ebd8cc3..55ed091 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/KeyEventHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/KeyEventHelper.kt
@@ -29,6 +29,10 @@
 class KeyEventHelper(
     private val instr: Instrumentation,
 ) {
+    fun press(keyCode: Int, metaState: Int = 0) {
+        actionDown(keyCode, metaState)
+        actionUp(keyCode, metaState)
+    }
 
     fun actionDown(keyCode: Int, metaState: Int = 0, time: Long = SystemClock.uptimeMillis()) {
         injectKeyEvent(ACTION_DOWN, keyCode, metaState, downTime = time, eventTime = time)
diff --git a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
index aea75d8..d75a8f4 100644
--- a/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
+++ b/tests/Input/src/com/android/server/input/InputManagerServiceTests.kt
@@ -613,7 +613,8 @@
                 0
             },
             "title",
-            /* uid = */0
+            /* uid = */0,
+            /* inputFeatureFlags = */ 0
         )
         whenever(windowManagerInternal.getKeyInterceptionInfoFromToken(any())).thenReturn(info)
     }
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index 4959cb3..4d7085f 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -466,27 +466,27 @@
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
-                "META + ALT + DPAD_LEFT -> Change Splitscreen Focus Left",
+                "CTRL + ALT + DPAD_LEFT -> Change Splitscreen Focus Left",
                 intArrayOf(
-                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_LEFT
                 ),
                 KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
-                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
-                "META + CTRL + DPAD_RIGHT -> Change Splitscreen Focus Right",
+                "CTRL + ALT + DPAD_RIGHT -> Change Splitscreen Focus Right",
                 intArrayOf(
-                    KeyEvent.KEYCODE_META_LEFT,
+                    KeyEvent.KEYCODE_CTRL_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_RIGHT
                 ),
                 KeyGestureEvent.KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_RIGHT),
-                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
@@ -735,25 +735,25 @@
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
-                "META + ALT + '-' -> Magnifier Zoom Out",
+                "META + ALT + '-' -> Magnification Zoom Out",
                 intArrayOf(
                     KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_MINUS
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_OUT,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_OUT,
                 intArrayOf(KeyEvent.KEYCODE_MINUS),
                 KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
-                "META + ALT + '=' -> Magnifier Zoom In",
+                "META + ALT + '=' -> Magnification Zoom In",
                 intArrayOf(
                     KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_EQUALS
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_ZOOM_IN,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_ZOOM_IN,
                 intArrayOf(KeyEvent.KEYCODE_EQUALS),
                 KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
@@ -785,49 +785,49 @@
             TestData(
                 "META + ALT + 'Down' -> Magnification Pan Down",
                 intArrayOf(
-                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_DOWN
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_DOWN,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_DOWN,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_DOWN),
-                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
                 "META + ALT + 'Up' -> Magnification Pan Up",
                 intArrayOf(
-                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_UP
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_UP,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_UP,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_UP),
-                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
                 "META + ALT + 'Left' -> Magnification Pan Left",
                 intArrayOf(
-                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_LEFT
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_LEFT,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_LEFT,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_LEFT),
-                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
             TestData(
                 "META + ALT + 'Right' -> Magnification Pan Right",
                 intArrayOf(
-                    KeyEvent.KEYCODE_CTRL_LEFT,
+                    KeyEvent.KEYCODE_META_LEFT,
                     KeyEvent.KEYCODE_ALT_LEFT,
                     KeyEvent.KEYCODE_DPAD_RIGHT
                 ),
-                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFIER_PAN_RIGHT,
+                KeyGestureEvent.KEY_GESTURE_TYPE_MAGNIFICATION_PAN_RIGHT,
                 intArrayOf(KeyEvent.KEYCODE_DPAD_RIGHT),
-                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON,
+                KeyEvent.META_META_ON or KeyEvent.META_ALT_ON,
                 intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
             ),
         )
diff --git a/tests/Input/src/com/android/test/input/KeyCharacterMapTest.kt b/tests/Input/src/com/android/test/input/KeyCharacterMapTest.kt
index 2818379..860d9f6 100644
--- a/tests/Input/src/com/android/test/input/KeyCharacterMapTest.kt
+++ b/tests/Input/src/com/android/test/input/KeyCharacterMapTest.kt
@@ -16,10 +16,17 @@
 
 package com.android.test.input
 
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
+
 import android.view.KeyCharacterMap
 import android.view.KeyEvent
 
+import com.android.hardware.input.Flags
+
 import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Rule
 import org.junit.Test
 
 /**
@@ -30,26 +37,38 @@
  *
  */
 class KeyCharacterMapTest {
+    @get:Rule
+    val setFlagsRule = SetFlagsRule()
+
     @Test
+    @EnableFlags(Flags.FLAG_REMOVE_FALLBACK_MODIFIERS)
     fun testGetFallback() {
         // Based off of VIRTUAL kcm fallbacks.
         val keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD)
 
         // One modifier fallback.
-        assertEquals(
-            keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_SPACE,
-                KeyEvent.META_CTRL_ON).keyCode,
-            KeyEvent.KEYCODE_LANGUAGE_SWITCH)
+        val oneModifierFallback = keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_SPACE,
+            KeyEvent.META_CTRL_ON)
+        assertEquals(KeyEvent.KEYCODE_LANGUAGE_SWITCH, oneModifierFallback.keyCode)
+        assertEquals(0, oneModifierFallback.metaState)
 
         // Multiple modifier fallback.
-        assertEquals(
-            keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_DEL,
-                KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON).keyCode,
-            KeyEvent.KEYCODE_BACK)
+        val twoModifierFallback = keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_DEL,
+            KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON)
+        assertEquals(KeyEvent.KEYCODE_BACK, twoModifierFallback.keyCode)
+        assertEquals(0, twoModifierFallback.metaState)
 
         // No default button, fallback only.
-        assertEquals(
-            keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_BUTTON_A, 0).keyCode,
-            KeyEvent.KEYCODE_DPAD_CENTER)
+        val keyOnlyFallback =
+            keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_BUTTON_A, 0)
+        assertEquals(KeyEvent.KEYCODE_DPAD_CENTER, keyOnlyFallback.keyCode)
+        assertEquals(0, keyOnlyFallback.metaState)
+
+        // A key event that is not an exact match for a fallback. Expect a null return.
+        // E.g. Ctrl + Space -> LanguageSwitch
+        //      Ctrl + Alt + Space -> Ctrl + Alt + Space (No fallback).
+        val noMatchFallback = keyCharacterMap.getFallbackAction(KeyEvent.KEYCODE_SPACE,
+            KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON)
+        assertNull(noMatchFallback)
     }
 }
diff --git a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
index c61a250..0b281d8 100644
--- a/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
+++ b/tests/Input/src/com/android/test/input/UinputRecordingIntegrationTests.kt
@@ -21,6 +21,7 @@
 import android.graphics.PointF
 import android.hardware.input.InputManager
 import android.os.ParcelFileDescriptor
+import android.server.wm.CtsWindowInfoUtils.waitForWindowOnTop
 import android.util.Log
 import android.util.Size
 import android.view.InputEvent
@@ -113,6 +114,7 @@
             testName,
             size = testData.displaySize
         ).use { scenario ->
+            waitForWindowOnTop(scenario.activity.window)
             scenario.activity.window.decorView.requestUnbufferedDispatch(INPUT_DEVICE_SOURCE_ALL)
 
             try {
diff --git a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
index 49616c3..8ac3433 100644
--- a/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/CrashRecoveryTest.java
@@ -765,14 +765,14 @@
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException(e);
         }
-        watchdog.registerHealthObserver(rollbackObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, rollbackObserver);
         return rollbackObserver;
     }
     RescuePartyObserver setUpRescuePartyObserver(PackageWatchdog watchdog) {
         setCrashRecoveryPropRescueBootCount(0);
         RescuePartyObserver rescuePartyObserver = spy(RescuePartyObserver.getInstance(mSpyContext));
         assertFalse(RescueParty.isRebootPropertySet());
-        watchdog.registerHealthObserver(rescuePartyObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, rescuePartyObserver);
         return rescuePartyObserver;
     }
 
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 928e232..1c50cb1 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -54,7 +54,6 @@
 import android.provider.DeviceConfig;
 import android.util.AtomicFile;
 import android.util.LongArrayQueue;
-import android.util.Slog;
 import android.util.Xml;
 
 import androidx.test.InstrumentationRegistry;
@@ -231,8 +230,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -248,10 +247,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), SHORT_DURATION, observer2);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
                         new VersionedPackage(APP_B, VERSION_CODE)),
@@ -268,8 +267,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
         watchdog.unregisterHealthObserver(observer);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -285,10 +284,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
         watchdog.unregisterHealthObserver(observer2);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -305,8 +304,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
         moveTimeForwardAndDispatch(SHORT_DURATION);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -322,10 +321,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observer2);
         moveTimeForwardAndDispatch(SHORT_DURATION);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -344,14 +343,14 @@
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
         // Start observing APP_A
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
 
         // Then advance time half-way
         moveTimeForwardAndDispatch(SHORT_DURATION / 2);
 
         // Start observing APP_A again
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
 
         // Then advance time such that it should have expired were it not for the second observation
         moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1);
@@ -373,17 +372,17 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog1.registerHealthObserver(observer1, mTestExecutor);
-        watchdog1.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog1.registerHealthObserver(observer2, mTestExecutor);
-        watchdog1.startExplicitHealthCheck(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
+        watchdog1.registerHealthObserver(mTestExecutor, observer1);
+        watchdog1.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog1.registerHealthObserver(mTestExecutor, observer2);
+        watchdog1.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), SHORT_DURATION, observer2);
         // Then advance time and run IO Handler so file is saved
         mTestLooper.dispatchAll();
         // Then start a new watchdog
         PackageWatchdog watchdog2 = createWatchdog();
         // Then resume observer1 and observer2
-        watchdog2.registerHealthObserver(observer1, mTestExecutor);
-        watchdog2.registerHealthObserver(observer2, mTestExecutor);
+        watchdog2.registerHealthObserver(mTestExecutor, observer1);
+        watchdog2.registerHealthObserver(mTestExecutor, observer2);
         raiseFatalFailureAndDispatch(watchdog2,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
                         new VersionedPackage(APP_B, VERSION_CODE)),
@@ -405,10 +404,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
 
         // Then fail APP_A below the threshold
         for (int i = 0; i < watchdog.getTriggerFailureCount() - 1; i++) {
@@ -434,10 +433,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), SHORT_DURATION, observer1);
 
         // Then fail APP_C (not observed) above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -469,8 +468,8 @@
                 }
             };
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
 
         // Then fail APP_A (different version) above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -499,18 +498,17 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
 
         // Start observing for all impact observers
-        watchdog.registerHealthObserver(observerNone, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerHigh, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerHigh, Arrays.asList(APP_A, APP_B, APP_C),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerMid, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerMid, Arrays.asList(APP_A, APP_B),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerLow, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerLow, Arrays.asList(APP_A),
-                SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observerNone);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C, APP_D),
+                SHORT_DURATION, observerNone);
+        watchdog.registerHealthObserver(mTestExecutor, observerHigh);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C), SHORT_DURATION,
+                observerHigh);
+        watchdog.registerHealthObserver(mTestExecutor, observerMid);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), SHORT_DURATION,
+                observerMid);
+        watchdog.registerHealthObserver(mTestExecutor, observerLow);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observerLow);
 
         // Then fail all apps above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -549,18 +547,17 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
 
         // Start observing for all impact observers
-        watchdog.registerHealthObserver(observerNone, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerNone, Arrays.asList(APP_A, APP_B, APP_C, APP_D),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerHigh, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerHigh, Arrays.asList(APP_A, APP_B, APP_C),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerMid, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerMid, Arrays.asList(APP_A, APP_B),
-                SHORT_DURATION);
-        watchdog.registerHealthObserver(observerLow, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerLow, Arrays.asList(APP_A),
-                SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observerNone);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C, APP_D),
+                SHORT_DURATION, observerNone);
+        watchdog.registerHealthObserver(mTestExecutor, observerHigh);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B, APP_C), SHORT_DURATION,
+                observerHigh);
+        watchdog.registerHealthObserver(mTestExecutor, observerMid);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), SHORT_DURATION,
+                observerMid);
+        watchdog.registerHealthObserver(mTestExecutor, observerLow);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observerLow);
 
         // Then fail all apps above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -607,10 +604,10 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing for observerFirst and observerSecond with failure handling
-        watchdog.registerHealthObserver(observerFirst, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerFirst, Arrays.asList(APP_A), LONG_DURATION);
-        watchdog.registerHealthObserver(observerSecond, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerSecond, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observerFirst);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerFirst);
+        watchdog.registerHealthObserver(mTestExecutor, observerSecond);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerSecond);
 
         // Then fail APP_A above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -673,10 +670,10 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
 
         // Start observing for observerFirst and observerSecond with failure handling
-        watchdog.registerHealthObserver(observerFirst, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerFirst, Arrays.asList(APP_A), LONG_DURATION);
-        watchdog.registerHealthObserver(observerSecond, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observerSecond, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observerFirst);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerFirst);
+        watchdog.registerHealthObserver(mTestExecutor, observerSecond);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observerSecond);
 
         // Then fail APP_A above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -743,10 +740,10 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
 
         // Start observing for observer1 and observer2 with failure handling
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
 
         // Then fail APP_A above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -767,10 +764,10 @@
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_50);
 
         // Start observing for observer1 and observer2 with failure handling
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer2);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
 
         // Then fail APP_A above the threshold
         raiseFatalFailureAndDispatch(watchdog,
@@ -800,10 +797,10 @@
         // Start observing with explicit health checks for APP_A and APP_B respectively
         // with observer1 and observer2
         controller.setSupportedPackages(Arrays.asList(APP_A, APP_B));
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), SHORT_DURATION, observer2);
 
         // Run handler so requests are dispatched to the controller
         mTestLooper.dispatchAll();
@@ -819,8 +816,8 @@
         // Observer3 didn't exist when we got the explicit health check above, so
         // it starts out with a non-passing explicit health check and has to wait for a pass
         // otherwise it would be notified of APP_A failure on expiry
-        watchdog.registerHealthObserver(observer3, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer3, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer3);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer3);
 
         // Then expire observers
         moveTimeForwardAndDispatch(SHORT_DURATION);
@@ -850,9 +847,9 @@
 
         // Start observing with explicit health checks for APP_A and APP_B
         controller.setSupportedPackages(Arrays.asList(APP_A, APP_B, APP_C));
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_B), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), LONG_DURATION, observer);
 
         // Run handler so requests are dispatched to the controller
         mTestLooper.dispatchAll();
@@ -888,7 +885,7 @@
         // Then set new supported packages
         controller.setSupportedPackages(Arrays.asList(APP_C));
         // Start observing APP_A and APP_C; only APP_C has support for explicit health checks
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A, APP_C), SHORT_DURATION);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_C), SHORT_DURATION, observer);
 
         // Run handler so requests/cancellations are dispatched to the controller
         mTestLooper.dispatchAll();
@@ -919,8 +916,8 @@
         // package observation duration == LONG_DURATION
         // health check duration == SHORT_DURATION (set by default in the TestController)
         controller.setSupportedPackages(Arrays.asList(APP_A));
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), LONG_DURATION, observer);
 
         // Then APP_A has exceeded health check duration
         moveTimeForwardAndDispatch(SHORT_DURATION);
@@ -951,8 +948,8 @@
         // package observation duration == SHORT_DURATION / 2
         // health check duration == SHORT_DURATION (set by default in the TestController)
         controller.setSupportedPackages(Arrays.asList(APP_A));
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION / 2);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION / 2, observer);
 
         // Forward time to expire the observation duration
         moveTimeForwardAndDispatch(SHORT_DURATION / 2);
@@ -1025,7 +1022,7 @@
         // Start observing with failure handling
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
-        wd.startExplicitHealthCheck(observer, Collections.singletonList(APP_A), SHORT_DURATION);
+        wd.startExplicitHealthCheck(Collections.singletonList(APP_A), SHORT_DURATION, observer);
 
         // Notify of NetworkStack failure
         mConnectivityModuleCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
@@ -1045,7 +1042,7 @@
         // Start observing with failure handling
         TestObserver observer = new TestObserver(OBSERVER_NAME_1,
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_100);
-        wd.startExplicitHealthCheck(observer, Collections.singletonList(APP_A), SHORT_DURATION);
+        wd.startExplicitHealthCheck(Collections.singletonList(APP_A), SHORT_DURATION, observer);
 
         // Notify of NetworkStack failure
         mConnectivityModuleCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
@@ -1066,8 +1063,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer);
         // Fail APP_A below the threshold which should not trigger package failures
         for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
             watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -1095,8 +1092,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A, APP_B), Long.MAX_VALUE, observer);
         watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1);
@@ -1129,8 +1126,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), -1);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), -1, observer);
         // Note: Don't move too close to the expiration time otherwise the handler will be thrashed
         // by PackageWatchdog#scheduleNextSyncStateLocked which keeps posting runnables with very
         // small timeouts.
@@ -1152,8 +1149,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), -1);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), -1, observer);
         moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS + 1);
         raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
@@ -1175,8 +1172,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, Arrays.asList(APP_A), Long.MAX_VALUE);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), Long.MAX_VALUE, observer);
         // Raise 2 failures at t=0 and t=900 respectively
         watchdog.notifyPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -1203,10 +1200,10 @@
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
         TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
 
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
-        watchdog.registerHealthObserver(observer2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer2, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
+        watchdog.registerHealthObserver(mTestExecutor, observer2);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), SHORT_DURATION, observer2);
 
         raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
                 VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_CRASH);
@@ -1225,8 +1222,8 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
 
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_A), SHORT_DURATION, observer1);
 
         raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
                 VERSION_CODE)), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
@@ -1246,8 +1243,8 @@
         persistentObserver.setPersistent(true);
         persistentObserver.setMayObservePackages(true);
 
-        watchdog.registerHealthObserver(persistentObserver, mTestExecutor);
-        watchdog.startExplicitHealthCheck(persistentObserver, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, persistentObserver);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), SHORT_DURATION, persistentObserver);
 
         raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
                 VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -1265,8 +1262,8 @@
         persistentObserver.setPersistent(true);
         persistentObserver.setMayObservePackages(false);
 
-        watchdog.registerHealthObserver(persistentObserver, mTestExecutor);
-        watchdog.startExplicitHealthCheck(persistentObserver, Arrays.asList(APP_B), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, persistentObserver);
+        watchdog.startExplicitHealthCheck(Arrays.asList(APP_B), SHORT_DURATION, persistentObserver);
 
         raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
                 VERSION_CODE)), PackageWatchdog.FAILURE_REASON_UNKNOWN);
@@ -1277,11 +1274,10 @@
     /** Ensure that boot loop mitigation is done when the number of boots meets the threshold. */
     @Test
     public void testBootLoopDetection_meetsThreshold() {
-        Slog.w("hrm1243", "I should definitely be here try 1 ");
         mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
         }
@@ -1293,7 +1289,7 @@
     public void testBootLoopDetection_meetsThresholdRecoverability() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
@@ -1309,7 +1305,7 @@
     public void testBootLoopDetection_doesNotMeetThreshold() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT - 1; i++) {
             watchdog.noteBoot();
         }
@@ -1326,7 +1322,7 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT - 1; i++) {
             watchdog.noteBoot();
         }
@@ -1345,8 +1341,8 @@
         bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
         TestObserver bootObserver2 = new TestObserver(OBSERVER_NAME_2);
         bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
-        watchdog.registerHealthObserver(bootObserver1, mTestExecutor);
-        watchdog.registerHealthObserver(bootObserver2, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver1);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver2);
         for (int i = 0; i < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; i++) {
             watchdog.noteBoot();
         }
@@ -1362,8 +1358,8 @@
         bootObserver1.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_10);
         TestObserver bootObserver2 = new TestObserver(OBSERVER_NAME_2);
         bootObserver2.setImpact(PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
-        watchdog.registerHealthObserver(bootObserver1, mTestExecutor);
-        watchdog.registerHealthObserver(bootObserver2, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver1);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver2);
         for (int i = 0; i < 15; i++) {
             watchdog.noteBoot();
         }
@@ -1380,7 +1376,7 @@
         mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int i = 0; i < 4; i++) {
             for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT; j++) {
                 watchdog.noteBoot();
@@ -1403,7 +1399,7 @@
         PackageWatchdog watchdog = createWatchdog();
         TestObserver bootObserver = new TestObserver(OBSERVER_NAME_1,
                 PackageHealthObserverImpact.USER_IMPACT_LEVEL_30);
-        watchdog.registerHealthObserver(bootObserver, mTestExecutor);
+        watchdog.registerHealthObserver(mTestExecutor, bootObserver);
         for (int j = 0; j < PackageWatchdog.DEFAULT_BOOT_LOOP_TRIGGER_COUNT - 1; j++) {
             watchdog.noteBoot();
         }
@@ -1431,8 +1427,8 @@
     public void testNullFailedPackagesList() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(observer1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer1, List.of(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer1);
+        watchdog.startExplicitHealthCheck(List.of(APP_A), LONG_DURATION, observer1);
 
         raiseFatalFailureAndDispatch(watchdog, null, PackageWatchdog.FAILURE_REASON_APP_CRASH);
         assertThat(observer1.mMitigatedPackages).isEmpty();
@@ -1450,18 +1446,18 @@
         PackageWatchdog watchdog = createWatchdog(testController, true);
 
         TestObserver testObserver1 = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(testObserver1, mTestExecutor);
-        watchdog.startExplicitHealthCheck(testObserver1, List.of(APP_A), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, testObserver1);
+        watchdog.startExplicitHealthCheck(List.of(APP_A), LONG_DURATION, testObserver1);
         mTestLooper.dispatchAll();
 
         TestObserver testObserver2 = new TestObserver(OBSERVER_NAME_2);
-        watchdog.registerHealthObserver(testObserver2, mTestExecutor);
-        watchdog.startExplicitHealthCheck(testObserver2, List.of(APP_B), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, testObserver2);
+        watchdog.startExplicitHealthCheck(List.of(APP_B), LONG_DURATION, testObserver2);
         mTestLooper.dispatchAll();
 
         TestObserver testObserver3 = new TestObserver(OBSERVER_NAME_3);
-        watchdog.registerHealthObserver(testObserver3, mTestExecutor);
-        watchdog.startExplicitHealthCheck(testObserver3, List.of(APP_C), LONG_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, testObserver3);
+        watchdog.startExplicitHealthCheck(List.of(APP_C), LONG_DURATION, testObserver3);
         mTestLooper.dispatchAll();
 
         watchdog.unregisterHealthObserver(testObserver1);
@@ -1493,15 +1489,15 @@
     public void testFailureHistoryIsPreserved() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, List.of(APP_A), SHORT_DURATION);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(List.of(APP_A), SHORT_DURATION, observer);
         for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
             watchdog.notifyPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
                     PackageWatchdog.FAILURE_REASON_UNKNOWN);
         }
         mTestLooper.dispatchAll();
         assertThat(observer.mMitigatedPackages).isEmpty();
-        watchdog.startExplicitHealthCheck(observer, List.of(APP_A), LONG_DURATION);
+        watchdog.startExplicitHealthCheck(List.of(APP_A), LONG_DURATION, observer);
         watchdog.notifyPackageFailure(List.of(new VersionedPackage(APP_A, VERSION_CODE)),
                 PackageWatchdog.FAILURE_REASON_UNKNOWN);
         mTestLooper.dispatchAll();
@@ -1516,9 +1512,9 @@
     public void testMitigationSlidingWindow() {
         PackageWatchdog watchdog = createWatchdog();
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
-        watchdog.registerHealthObserver(observer, mTestExecutor);
-        watchdog.startExplicitHealthCheck(observer, List.of(APP_A),
-                PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS * 2);
+        watchdog.registerHealthObserver(mTestExecutor, observer);
+        watchdog.startExplicitHealthCheck(List.of(APP_A),
+                PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS * 2, observer);
 
 
         raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
diff --git a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
index 44aa402..370c004 100644
--- a/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
+++ b/tests/inputmethod/ConcurrentMultiSessionImeTest/Android.bp
@@ -38,6 +38,9 @@
     ],
     test_suites: [
         "general-tests",
+        // This is an equivalent of general-tests for automotive.
+        // It helps manage the build time on automotive branches.
+        "automotive-general-tests",
     ],
     sdk_version: "test_current",
 
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index 5e0f87f..60c4bf5 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -292,13 +292,12 @@
             }
             if (!hasData) {
                 const String8& srcName = file->getSourceFile();
-                time_t fileModWhen;
-                fileModWhen = getFileModDate(srcName.c_str());
-                if (fileModWhen == (time_t) -1) { // file existence tested earlier,
-                    return false;                 //  not expecting an error here
+                auto fileModWhen = getFileModDate(srcName.c_str());
+                if (fileModWhen == kInvalidModDate) { // file existence tested earlier,
+                    return false;                     //  not expecting an error here
                 }
-    
-                if (fileModWhen > entry->getModWhen()) {
+
+                if (toTimeT(fileModWhen) > entry->getModWhen()) {
                     // mark as deleted so add() will succeed
                     if (bundle->getVerbose()) {
                         printf("      (removing old '%s')\n", storageName.c_str());
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 661df4d..e24fe07 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -683,8 +683,6 @@
       item->PrettyPrint(printer_);
       printer_->Print(")");
     }
-
-    printer_->Print("\n");
   }
 
   void PrintQualifiers(uint32_t qualifiers) const {
@@ -763,11 +761,13 @@
 
   bool PrintTableType(const ResTable_type* chunk) {
     printer_->Print(StringPrintf(" id: 0x%02x", android::util::DeviceToHost32(chunk->id)));
-    printer_->Print(StringPrintf(
-        " name: %s",
-        android::util::GetString(type_pool_, android::util::DeviceToHost32(chunk->id) - 1)
-            .c_str()));
+    const auto name =
+        android::util::GetString(type_pool_, android::util::DeviceToHost32(chunk->id) - 1);
+    printer_->Print(StringPrintf(" name: %s", name.c_str()));
     printer_->Print(StringPrintf(" flags: 0x%02x", android::util::DeviceToHost32(chunk->flags)));
+    printer_->Print(android::util::DeviceToHost32(chunk->flags) & ResTable_type::FLAG_SPARSE
+                        ? " (SPARSE)"
+                        : " (DENSE)");
     printer_->Print(
         StringPrintf(" entryCount: %u", android::util::DeviceToHost32(chunk->entryCount)));
     printer_->Print(
@@ -777,8 +777,7 @@
     config.copyFromDtoH(chunk->config);
     printer_->Print(StringPrintf(" config: %s\n", config.to_string().c_str()));
 
-    const ResourceType* type = ParseResourceType(
-        android::util::GetString(type_pool_, android::util::DeviceToHost32(chunk->id) - 1));
+    const ResourceType* type = ParseResourceType(name);
 
     printer_->Indent();
 
@@ -817,11 +816,8 @@
         for (size_t i = 0; i < map_entry_count; i++) {
           PrintResValue(&(maps[i].value), config, type);
 
-          printer_->Print(StringPrintf(
-              " name: %s name-id:%d\n",
-              android::util::GetString(key_pool_, android::util::DeviceToHost32(maps[i].name.ident))
-                  .c_str(),
-              android::util::DeviceToHost32(maps[i].name.ident)));
+          printer_->Print(StringPrintf(" name-id: 0x%08x\n",
+                                       android::util::DeviceToHost32(maps[i].name.ident)));
         }
       } else {
         printer_->Print("\n");
@@ -829,6 +825,8 @@
         // Print the value of the entry
         Res_value value = entry->value();
         PrintResValue(&value, config, type);
+
+        printer_->Print("\n");
       }
 
       printer_->Undent();